Design Pattern | Singleton Pattern (싱글톤 패턴)

Singleton 패턴이란?

  • Singleton(싱글톤)이란 하나의 요소만 가진 집합 이라는 의미이다.
  • Singleton 패턴은 인스턴스가 하나만 존재하는지를 보증하는 방식이다.
  • Singleton 패턴은 프로그램 내에서 인스턴스를 한번만 생성하도록 하고 싶을 때 사용된다.
  • 전역 변수를 사용하지 않고 객체를 하나만 생성 하도록 하며, 생성된 객체를 어디에서든지 참조할 수 있도록 하는 패턴이다.
  • 프로그램의 전역에서 사용될 설정 정보 값은 Singleton 패턴을 이용해 한개만 생성해 정보를 공유 하는데도 필요하다.
  • 예를 들어, 시스템 설정을 표현한 클래스, 윈도우 시스템을 표현한 클래스 등을 들 수 있다.
  • GoF 디자인 패턴에서는 생성과 관련된 디자인 패턴으로 분류된다.

Singleton 패턴 예제 프로그램

싱글 톤 인스턴스를 생성하는 프로그램이다.

Class Diagram
Singleton Pattern Class Diagram

1. Singleton 클래스

유일한 인스턴스를 반환하는 클래스이다.
Singleton 클래스의 생성자는 private으로 지정한다. 이는 Singleton 클래스 밖에서 생성자를 호출하는 것을 못하게 하기 위함이다.

Singleton.java

package com.devkuma.designpattern.creational.singleton.ex1;

public class Singleton {

    private static Singleton singleton = new Singleton();

    private Singleton() {
        System.out.println("인스턴스를 생성하였습니다.");
    }

    public static Singleton getInstance() {
        return singleton;
    }
}

2. Main 클래스

메인 처리를 실행하는 클래스이다.

Main.java

package com.devkuma.designpattern.creational.singleton.ex1;

public class Main {
    public static void main(String[] args) {
        Singleton obj1 = Singleton.getInstance();
        Singleton obj2 = Singleton.getInstance();
        if (obj1 == obj2) {
            System.out.println("obj1와 obj2는 동일한 인스턴스입니다.");
        } else {
            System.out.println("obj1와 obj2는 동일한 인스턴스가 아닙니다.");
        }
    }
}

3. 실행 결과

인스턴스를 생성하였습니다.
obj1와 obj2는 동일한 인스턴스입니다.

Singleton 패턴의 장점

Singleton 패턴은 인스턴스 수에 제한을 두고 있다.
인스턴스가 여러 개 존재하면 인스턴스가 서로 영향을 미치고 뜻밖의 버그를 만들 수 있다.
그러나 인스턴스가 하나만 있다는 보장이 있다면 그 전제조건으로 프로그래밍할 수 있다.

synchronized를 사용한 Singleton 패턴

synchronized를 사용한 Singleton 패턴 프로그램 예제

여러 객체에서 동시에 접근을 할 수 있기에 synchronized를 선언을 해야 스레드로 부터 안전하다.

package com.devkuma.designpattern.creational.singleton.ex2;

public class SynchronizedSingleton1 {

    private static Singleton1 instance;

    /**
     * 접근할 수 없는 생성자
     */
    private SynchronizedSingleton1() {
    }

    public static synchronized Singleton1 getInstance() {
        if (instance == null) {
            instance = new Singleton1();
        }
        return instance;
    }

    public static void main(String[] args) {

        Singleton1 singleton1 = Singleton1.getInstance();
        Singleton1 singleton2 = Singleton1.getInstance();

        System.out.println(singleton1);
        System.out.println(singleton2);
    }
}

synchronized 성능 개선한 Singleton 패턴 프로그램 예제

동기화 때문에 성능관련 이슈가 발생할 수 있기 때문에 아래와 같은 코드를 작성해 최초 한번만 동기화하도록 해서 성능을 향상 시킬 수 있다.

  • volatile: 스레딩 환경에서 하나의 변수가 완벽하게 한번에 작동하도록 보장하는 키워드
package com.devkuma.designpattern.creational.singleton.ex2;

public class SynchronizedSingleton2 {

    private volatile static Singleton2 instance;

    /**
     * 접근할 수 없는 생성자
     */
    private SynchronizedSingleton2() {
    }

    public static Singleton2 getInstance() {
        if (instance == null) {
            // 처음 한번만 인스턴스가 생성된다.
            synchronized (Singleton2.class) {
                if (instance == null) {
                    instance = new Singleton2();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {

        Singleton2 singleton1 = Singleton2.getInstance();
        Singleton2 singleton2 = Singleton2.getInstance();

        System.out.println(singleton1);
        System.out.println(singleton2);
    }
}