JAVA Basic ) static 응용 - 싱클톤 패턴
Programming/Java 기초

JAVA Basic ) static 응용 - 싱클톤 패턴

728x90

 

목차


     

    싱글톤 패턴? - (singleton pattern)

    프로그램을 구현하다 보면 여러 개의 인스턴스가 필요한 경우도 있고, 단 하나의 인스턴스만 필요한 경우도 있다.
    객체 지향 프로그램에서 인스턴스를 단 하나만 생성하는 디자인 팬턴'싱글톤 패턴(singleton pattern)'이라고 한다.

    여기서 살펴볼 싱글톤 패턴은 static을 응용하여 프로그램 전반에서 사용하는 인스턴스를 하나만 구현하는 방식이다.
    실무, 어러 프레임워크에서 많이 사용되는 패턴이므로 잘 익혀두면 좋을 것이다.


     

    어떤 회사의 직원들을 프로그램으로 구현한다고 해보자.
    직원은 여러 명이므로 여러 개의 인스턴스가 필요한 것은 당연하지만,
    회사는 하나이므로 하나의 인스터스만 생성해야 한다.

    그러면 싱글톤 패턴으로 company 클래스를 단계적으로 만들어 보자.

     

     

    〈싱글톤 패턴으로 회사 Company 클래스 구현하기〉

    단계 1 : 생성자를 private로 만들기

    생성자가 하나도 없는 클래스는 컴파일러가 자동으로 디폴트 생성자를 만든다. 하지만 디폴트 생성자는 항상 public이다. 생성자가 public이면 외부 클래스에서 인스턴스를 여러개 생성할 수 있게 된다. 따라서 싱글톤 패턴에서는 생성자의 접근 제어자를 반드시 private로 지정해야 한다. 그래야 외부 클래스에서 마음대로 Company 인스턴스를 생성할 수 없게 된다. 즉 Company 내부에서만 이 클래스의 생성을 제어할 수 있다.

    package singleton;
    
    public class Company {
    	private Company() {} 
    	/* 접근 제어자를 private으로 선언하여
    	 * 외부에서 company 인스턴스를 생성하지 못하도록 한다.*/
    }


    단계 2 : 클래스 내부에 static으로 유일한 인스턴스 생성하기

    1단계에서 외부 인스턴스를 생성할 수 없도록 했다.
    하지만 우리가 프로그램에서 사용하기 위해서는 하나 이상의 인스턴스는 필요하다.
    따라서 Company클래스 내부에서 하나의 인스턴스를 생성합니다. 이 인스턴스가 프로그램 전체에서 사용할 유일한 인스턴스가 된다.
    또한 private으로 선언하여 외부에서 이 인스턴스에 접근하지 못하도록 제한해야 인스턴스 오류를 방지할 수 있다.

    package singleton;
    
    public class Company {
    	private static Company instance = new Company();
    	//유일하게 생성한 인스턴스
    	
    	private Company() {} 
    	/* 접근 제어자를 private으로 선언하여
    	 * 외부에서 company 인스턴스를 생성하지 못하도록 한다.*/
    }


    단계 3 : 외부에서 참조할 수 있는 public 메서드 만들기

    이제 private으로 선언한 유일한 인스턴스를 외부에서도 사용할 수 있도록 설정해야 한다.
    이를 위해 public 메서드를 생성한다. 그리고 유일하게 생성한 인스턴스를 반환해 줍니다.
    이때 인스턴스를 반환하는 메서드는 반드시 static으로 선언해야 합니다. 왜냐하면 getInstance()메서드는 인스턴스 생성과 상관없이 호출할 수 있어야 하기 때문이다.

    package singleton;
    
    public class Company {
    	private static Company instance = new Company();
    	//유일하게 생성한 인스턴스
    	
    	private Company() {} 
    	/* 접근 제어자를 private으로 선언하여
    	 * 외부에서 company 인스턴스를 생성하지 못하도록 한다.*/
    	
    	public static Company getInstance() {
    	/* 인스턴스를 외부에서 참조하지 못하도록
    	 * public get()메서드를 구현 */
    		if(instance == null) {
    			instance = new Company();
    		}
    		return instance; // 유일하게 생성한 인스턴스를 반환
    	}
    }

     

    단계 4 : 실제로 사용하는 코드 작성하기

    외부 클래스에서는 Company를 생성할 수 없으므로 static으로 제공되는 getInstance() 메서드를 호출합니다.
    Company.getInstance();와 같이 호출하면 반환 값으로 유일한 인스턴스를 받아 옵니다.

    package singleton;
    
    public class CompanyTest {
    
    	public static void main(String[] args) {
    		Company C1 = Company.getInstance();
    		Company C2 = Company.getInstance();
    		/* 클래스 이름으로 getInstance()메서드를 호출하여
    		 *참조 변수(C1, C2)에 대입*/
    		System.out.println(C1);
    		System.out.println(C2);
    	}
    }

    출력 값 :

    C1, C2 참조 값 동일

    C1과 C2를 비교하면 같은 참조 값을 가지는 동일한 인스턴스임을 알 수 있다.
    Company 클래스는 내부에 생성된 유일한 인스턴스 외에는 더 이상 인스턴스를 생성할 수 없다.
    이와 같이 static을 사용하여 유일한 객체를 생성하는 싱글톤 패턴을 구현할 수 있다.


    연습 문제

    자동차 공장이 있다. 자동차 공장은 유일한 객체이고, 이 공장에서 생산되는 자동차는 제작될 때마다 고유 번호가 부여된다. 자동차 번호가 10001부터 시작되어 자동차가 생성될 때마다 10002, 10003 이렇게 번호가 붙도록 자동차 공장 클래스, 자동차 클래스를 만들어보자. 두 클래스는 다음의 CarfactoryTest.java테스트 코드가 수행될 수 있도록 구현해 보자.

    package chapter6;
    public class CarFactoryTest {
    	public static void main(String[] args) {
    
    		CarFactory factory = CarFactory.getInstance();	//싱글톤 패턴
    		Car mySonata = factory.createCar();		//메서드에서 Car 생성	
    		Car yourSonata = factory.createCar();
    		
    		System.out.println(mySonata.getCarNum());	//10001출력
    		System.out.println(yourSonata.getCarNum());	//10002 출력
    	}
    }

    풀이 :

    package chapter6;
    
    public class CarFactory {
    	
    	private static CarFactory instance = new CarFactory();
    	
    	private CarFactory() {}
    	
    	public static CarFactory getInstance() {
    		if(instance == null) {
    			instance = new CarFactory();
    		}
    		return instance;
    	}
    	public Car createCar() {
    		Car car = new Car();
    		return car;
    	// 새로운 차를 생성하는 createCar()메서드를 구현
    	}
    }
    package chapter6;
    
    public class Car {
    	static int serialNum = 10000;
    	public int carNum;
    	
    	Car(){
    		serialNum++;
    		carNum = serialNum;
    	}
    		
    	public int getCarNum() {
    		return carNum;
    	}
    	public void setCarNum(int carNum) {
    		this.carNum = carNum;
    	}
    }

    출력 결과 :


    [Do it! 자바 프로그래밍 입문] 도서로 공부하며 정리한 글입니다.

    300x250