Design Patter1: Singleton Pattern

업데이트:
1 분 소요

비트캠프 서초본원 엄진영 강사님의 수업을 듣고 정리했습니다.


Singleton Pattern

1. Singleton Pattern이란?

클래스의 객체를 두 개 이상 생성하지 못하도록 생성자에 직접 접근하는 것을 막고, 대신 객체를 생성하는 다른 스태틱 메서드를 제공하는 방식으로 클래스를 설계하는 방식이다.

객체를 하나만 생성하는 메서드의 원리

  • 클래스를 선언하는데, 생성자의 접근 제한자를 private으로 한다.
    • 접근 제한자를 private으로 하면 생성자를 외부에서는 호출할 수 없고 오직 내부에서만 호출할 수 있다.
  • 인스턴스를 생성하는 스태틱 메서드를 선언한다.
    • 이미 인스턴스가 있다면 그 인스턴스를 리턴하고, 기존에 생성된 인스턴스가 없다면 새로운 인스턴스를 생성하도록 한다.

인스턴스를 딱 한 개만 생성하여 공유하고 싶다면, Singleton 설계 방식으로 클래스를 정의하라!

2. Signleton Pattern 적용

Singleton 적용 전

  • 생성자를 따로 정의하지 않기 때문에 컴파일 과정에서 기본 생성자가 자동으로 추가된다.
    • 생성자를 호출할 때마다 인스턴스를 만들 수 있기 때문에 인스턴스를 여러 개 생성할 수 있다.
class Car1 {
  String model;
  int cc;

  // 기본 생성자 자동 추가
  //public Car1() {}
}

public class Test01 {
  public static void main(String[] args) {
    // 인스턴스 생성
    Car1 c1 = new Car1();
    Car1 c2 = new Car1();

    System.out.println(c1 == c2);
  }
}

Singleton 적용 후

  • 생성자가 존재하지만 private으로 비공개 되어 있기 때문에 직접 호출할 수 없다.
  • 생성자를 호출할 수 없으면 인스턴스를 생성할 수 없다.
  • 다른 메서드를 호출하여 인스턴스를 생성하라는 의미다.
class Car2 {
  String model;
  int cc;

  // 인스턴스 주소를 받을 클래스 필드를 선언한다.
  private static Car2 instance;

  // 1) 생성자를 정의하고 private으로 선언한다.
  private Car2() {}

  // 2) 인스턴스를 생성해주는 스태틱 메서드를 정의한다.
  public static Car2 getInstance() {
    if (Car2.instance == null) {
      // 아직 인스턴스를 생성한 적이 없다면,
      // 즉시 인스턴스를 생성한다.
      Car2.instance = new Car2();
    }

    // 이미 인스턴스가 있다면,
    // 기존에 변수에 저장된 인스턴스 주소를 리턴한다.
    return Car2.instance;
  }
}

public class Test02 {
  public static void main(String[] args) {

    // 생성자가 private으로 비공개 되어 있다.
    // 생성자를 호출할 수 없으면 인스턴스를 생성할 수 없다.
    //Car2 c1 = new Car2(); // 컴파일 오류!

    Car2 c2 = Car2.getInstance();
    Car2 c3 = Car2.getInstance();
    Car2 c4 = Car2.getInstance();

    System.out.println(c2 == c3);
    System.out.println(c3 == c4);
  }
}

Singleton 연습

  • 김밥 인스턴스를 한 개만 생성하도록 Singleton 패턴을 적용하라.
class Kimbap {

  private static Kimbap instance;

  private Kimbap () {}

  public static Kimbap getInstance() {
    if(Kimbap.instance == null) {
      Kimbap.instance = new Kimbap();
    }
    return Kimbap.instance;
  }
}

public class Test03 {
  public static void main(String[] args) {
    // 아래 코드는 컴파일 오류!
    // Kimbap bap1 = new Kimbap();

    Kimbap bap2 = Kimbap.getInstance();
    Kimbap bap3 = Kimbap.getInstance();
    System.out.println(bap2 == bap3); // true
  }
}