개발이좋아

[Java] 싱글톤 패턴 (Singleton Pattern) 본문

Java

[Java] 싱글톤 패턴 (Singleton Pattern)

noobdev 2019. 12. 14. 20:45

싱글톤 패턴은 단 하나의 인스턴스만을 생성하고 사용하는 디자인 패턴을 뜻한다.

 

※디자인 패턴 : 객체 지향 프로그램을 어떻게 하면 더 유연하고 재활용성이 높게 프로그래밍할 수 있는지를 정리한 패턴.

 

싱글톤 패턴은 인스턴스를 단 하나만 생성하고 사용하기 때문에 클래스의 생성자를 선언할 때 접근제어자를 private으로 선언한다.

또한 static 예약어를 응용하여 프로그램 전반에서 사용하는 인스턴스를 하나만 생성하고 공유할 수 있도록 한다.

 

자바에서 싱글톤 패턴을 구현하는 단계는 아래와 같다.

  1.  생성자를 private으로 만들기
  2.  클래스 내부에 static으로 유일한 인스턴스 생성하기
  3.  외부에서 참조 가능한 public getter  메서드 만들기 
  4.  클래스를 실제로 사용하는 코드 만들기

싱글톤 패턴은 static예약어를 통해 인스턴스를 딱 하나 생성하여 언제 어느 클래스에서든 접근할 수 있도록 하기 위하여 사용하는 패턴이고 하나의 클래스만 사용해야 하는 경우에 유용한 패턴이다.

 


 

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

private 클래스이름 ( ) { }

 

위 코드와 같은 형식으로 클래스에 접근제어자를 private으로한 디폴트 생성자를 만든다.

클래스의 생성자가 없으면 컴파일러가 자동으로 디폴트 생성자를 생성하는데 컴파일러가 만들어주는 디폴트 생성자는 public 접근제어자를 가진다.

싱글톤 패턴은 인스턴스를 단 하나만 사용하므로 두 개이상의 인스턴스를 생성하면 안 되기 때문에 private로 디폴트 생성자를 만들어 인스턴스가 두 개 이상 생성되는 일을 막는다. 

접근 제어자를 private으로 한 생성자를 만들면 외부 클래스에서 접근을 하지 못하므로 인스턴스를 생성할 수 없게 된다.

 

 


 

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

 

private static 클래스이름 instance = new 클래스이름( );  //유일하게 생성하는 인스턴스

private 클래스이름 ( ) { }  //1단계에서 만들어준 private 디폴트 생성자

 

1단계에서 외부 클래스에서 싱글톤 클래스의 인스턴스를 생성하지 못하게 만들었기 때문에 싱글톤 클래스에서 인스턴스를 자체적으로 하나 만들어주도록 한다.  이렇게 만든 싱글톤 클래스의 인스턴스가 프로그램 전체에서 사용하는 유일한 인스턴스이다. 

또한 private으로 선언해야 외부에서 이 인스턴스에 접근을 하지 못하기 때문에 오류를 방지할 수 있다.

 

인스턴스를 선언할 때 static 예약어를 붙여주면 다른 클래스에서 인스턴스를 생성하지 않고도 클래스 이름으로 바로 싱글톤 패턴에서 생성한 인스턴스를 접근할 수 있다.

 

 

 


 

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

private static 클래스이름 instance = new 클래스이름( );  //2단계에서 만든 유일하게 생성하는 인스턴스

private 클래스이름 ( ) { }  //1단계에서 만들어준 private 디폴트 생성자

public static 클래스이름 getInstance( ) {	//인스턴스를 외부에서 참조할 수 있도록 public으로 메서드 선언
   if(instance == null) {
     instance = new 클래스이름( );
   }
   return instance;
 }

 

2단계에서 만든 인스턴스는 private이므로 외부 클래스에서 접근하지못한다. 

그러므로 public 접근제어자를 가진 getter 메서드를 만들어서 외부 클래스에서 유일하게 만든 인스턴스에 접근할 수 있도록 만든다.

이 메서드는 getter메서드로 인스턴스를 반환해주는 메서드이고, 선언 시 static 예약어를 반드시 붙여주어야 한다.

 

static 예약어를 붙여주는 이유는 외부 클래스에서 인스턴스에 생성과는 상관없이 클래스 이름으로 getter 메서드에 접근하기 위해서이다. 싱글톤 패턴의 의의는 인스턴스를 하나만 만들어 사용하는 것이기 때문에 외부 클래스에서 인스턴스가 생성되어서는 안 되므로 static 예약어를 이용한다.

 

 


4단계 실제로 사용하는 코드 만들기

싱글톤 클래스를 만들었으니 이제 싱글톤 클래스를 사용하는 외부 클래스를 만든다.

 

public class 클래스이름 {
  public static void main(String[ ] args) {
    싱글톤 클래스 이름   변수1  =  싱글톤 클래스 이름.getInstance();
    싱글톤 클래스 이름   변수2  =  싱글톤 클래스 이름.getInstance();
    
    System.out.println ( 변수1 == 변수2 );
    
   }
  } 

위 예제는 메인 메서드 안에 싱글톤 클래스형의 참조 변수를 2개 선언하고 싱글톤 클래스에서 만든 getter 메서드를 호출하는 예제이다.

3단계에서 만든 getter 메서드는 싱글톤 클래스의 인스턴스를 반환하는 메서드이므로 변수에는 싱글톤 클래스 인스턴스에 주소가 담긴다.

그 후 콘솔 창에 두 변수가 같은 주소를 가리키고 있는지 출력해보면 결과는 true를 반환한다.

 

 

 

싱글톤 내부에서 생성한 인스턴스 외에는 더 이상 인스턴스를 생성할 수 없다. 이와 같이 static 키워드를 이용하여 유일한 객체를 생성하고 사용하는 싱글톤 패턴을 구현할 수 있다.

 

 

 


싱글톤 패턴 예제

싱글톤 패턴은 하나의 유일한 객체를 만들고 이를 이용하는 패턴이라고 하였다. 

아래 예제는 자동차 공장이라는 유일한 객체에서 차 객체를 생성하고 차 객체가 생성될 때마다 차 객체가 가지는 고유한 번호가 1씩 증가되는 싱글톤 패턴을 이용한 간단한 예제이다.   

 

※소스코드 참고 : Do it! 자바 프로그래밍 입문

 

우선 필요한 클래스는 유일한 객체인 CarFactory와 자동차 공장에서 생성될 Car 클래스, main 메서드를 가지고 있는 테스트 클래스이다.

 

프로그램의 시나리오는 자동차 공장에서 차가 만들어지며 차가 만들어질 때마다 자동차의 속성 중 하나인 차 번호가 1씩 자동으로 증가하는 것이다.

 

  1. CarFactory 클래스에서 Car를 생성
  2. Car를 생성할 때마다 Car의 carNum 속성이 1씩 증가
  3. 테스트 클래스에서 carNum을 출력

 


 

CarFactory 클래스

자동차 공장의 역할을 하는 CarFactory 클래스는 유일한 객체이기 때문에 하나의 인스턴스만 생성하기 위해 클래스 내부적으로 인스턴스를 하나 생성하고 private 생성자를 이용하여 외부 클래스에서 CarFactory 클래스가 생성되는 것을 막는다.

 

외부 클래스에서 CarFactory 클래스의 인스턴스에 접근하기 위하여 public으로 getter 메서드를 하나 만든다.

 

자동차 공장의 역할을 하기 위해 Car 클래스를 생성하는 createCar( ) 메서드를 만든다.

 

 

 


 

Car 클래스

차 번호의 고유한 값을 만들기 위해 static 예약어로 serialNum 멤버 변수를 선언하고 이 변수의 값을 다른 클래스에서 공유할 수 있도록 만든다.

 

생성자에서는 Car클래스가 만들어질 때 serialNum멤버 변수가 1씩 증가하게 만든 후 carNum 변수의 serialNum의 값을 대입시킨다. 

결과적으로 Car클래스를 생성할 때마다 carNum의 값은 1씩 증가한다.

 

getter/setter 메서드를 선언하여 private 선언된 carNum의 값을 반환받을 수 있도록 한다.

 

 

 


 

 

테스트 클래스

유일한 객체인 CarFactory 객체를 이용하기 위해 getInstance( ) 메서드로 인스턴스를 불러온다.

 

Car 객체의 생성은 싱글톤 패턴을 적용한 factory 변수로 접근하여 createCar( ) 메서드로 객체를 생성한다. 

Car 객체는 생성될 때마다 차 번호가 1씩 증가한다. 

 

차 번호를 출력해주는 getCarNum( ) 메서드를 호출하여 차 번호를 콘솔의 출력한다.

 

 

위의 예제가 static을 이용한 싱글톤 패턴의 예이다.

 

 

 

 

 

 

본 포스팅은 필자가 공부한 것을 정리해놓은 것으로 오류가 존재할 수 있습니다.

참고 :  Do it! 자바 프로그래밍 입문

Comments