home > back-end > design-pattern > [design-pattern] singleton 패턴

[design-pattern] singleton 패턴
back-end design-pattern singleton

intro : singleton 패턴에 대해서 알아보자

singleton 패턴이란 ?

싱글톤 패턴(Singleton Pattern)은 객체지향 프로그래밍에서 사용되는 생성 디자인 패턴 중 하나로, 클래스의 인스턴스가 오직 하나만 존재하도록 보장하는 패턴입니다. 이 패턴은 클래스가 단 하나의 인스턴스를 공유해야 할 때 유용하며, 주로 시스템에서 전역적으로 접근 가능한 유일한 객체가 필요할 때 사용된다.

singleton 패턴은 언제 사용하는가 ?

싱글톤 패턴은 객체가 시스템 내에서 단 하나만 존재해야 할 때 사용합니다. 이 패턴은 전역적으로 공유되는 객체가 필요하거나, 여러 곳에서 동일한 인스턴스를 참조해야 할 때 유용하다.

singleton 패턴 적용 코드

싱글톤으로 사용할 클래스 정의. 예제의 상황은 시스템에 전역적으로 적용될 테마색(light,dark)에 대한 설정을 진행할 클래스와 해당 클래스를 이용하여 테마 색이 적용되는 버튼, 텍스트필드, 라벨에 대한 상황을 보겠다.

// 싱글톤으로 사용할 클래스
public class Theme {
    // 자기자신의 타입의 멤버변수를 선언한다.
    // static 키워드를 사용하는 이유는 전역적으로 하나만 사용하기 위함에 있음
    private static Theme instance;
    // 테마 칼라를 선언한다.
    private String themeColor;

    // 생성자가 private인 이유는, 외부에서 해당 클래스 객체를 new 연산자로
    // 생성하지 못하게 하기 위함에 있다.
    private Theme() {
        // 기본적으로 해당 객체가 생성되었을때는 테마 색은 light로 설정한다.
        this.themeColor = "light"; // Default theme
    }
    // 외부에서 객체를 생성하기 위해서는 해당 메서드를 이용해서 
    // 인스턴스를 반환받아야 한다.
    public static Theme getInstance() {
        // 만약 클래스의 instance 변수가 null 인경우
        // 객체가 생성되어 있지 않다는 걸로 간주하고 new 연산자를 통해 내부에서 객체 생성
        if (instance == null) {
            instance = new Theme();
        }
        // 만약 instance 객체가 생성되어 있다면 주소값만 리턴
        return instance;
    }

    // 테마 색을 얻는 메서드
    public String getThemeColor() {
        return themeColor;
    }
    // 테마 색을 설정하는 메서드
    public void setThemeColor(String themeColor) {
        this.themeColor = themeColor;
    }
}

각 버튼과 텍스트필드 라벨에 대한 클래스를 정의하고 해당 클래스의 테마색은 싱글톤 클래스의 (Theme) 설정에 따라 display 메서드에서 themeColor가 다르게 출력된다. (색을 따로 dark로 변경하기 전까지는 light가 기본값)

// 싱글톤 클래스에서 값을 참조할 클래스
public class Button {
    private String label;

    public Button(String label) {
        this.label = label;
    }

    // Theme.getInstance().getThemeColor(); 메서드가 실행 가능한 이유는
    // getInstance() 메서드가 static 메서드이기 때문에 객체 생성없이도 호출이 가능하다.
    // 전역적으로 하나만 존재하기에 getThemeColor 메서드 호출값은 어디서 호출하던지 동일한 값을 보장함
    public void display() {
        String themeColor = Theme.getInstance().getThemeColor();
        System.out.println(
            "Button [" + label + "] displayed in " + themeColor + " theme."
        );
    }
}

public class TextField {
    private String text;

    public TextField(String text) {
        this.text = text;
    }

    // 위 주석과 같은 맥락으로 static 메서드 이기 때문에 Theme.getInstance().getThemeColor(); 실행이 가능
    public void display() {
        String themeColor = Theme.getInstance().getThemeColor();
        System.out.println(
            "TextField [" + text + "] displayed in " + themeColor + " theme."
        );
    }
}

public class Label {
    private String text;

    public Label(String text) {
        this.text = text;
    }
    // 위 주석과 같은 맥락으로 static 메서드 이기 때문에 Theme.getInstance().getThemeColor(); 실행이 가능
    public void display() {
        String themeColor = Theme.getInstance().getThemeColor();
        System.out.println(
            "Label [" + text + "] displayed in " + themeColor + " theme."
        );
    }
}

클라이언트 코드에서는 버튼, 텍스트필드, 라벨에 대한 객체를 생성하고 display 메서드를 호출한다. 간단하게 싱글톤 클래스에서 테마 색을 관리하고 있기에, Theme.getInstance().setThemeColor("dark"); 라인 이후에 다시 display 메서드를 호출하면 dark가 출력된다. 이와 같이 싱글톤 패턴으로 시스템 전역에 적용되어야 하는 설정값을 하나의 객체로 관리 할 수 있다.

// Client code
public class Main {
    public static void main(String[] args) {
        Button button = new Button("Submit");
        TextField textField = new TextField("Enter your name");
        Label label = new Label("Username");

        // display 메서드는 내부적으로 테마 색을 출력하도록 되어있음
        // 기본적으로 light가 기본값이기에, 이시점에서는 light로 출력됨
        button.display();
        textField.display();
        label.display();

        // 테마 색을 dark로 변경
        Theme.getInstance().setThemeColor("dark");

        // 아래 출력문은 테마색이 dark로 변경되어 출력됨
        button.display();
        textField.display();
        label.display();
    }
}

singleton 패턴 요약

싱글톤 패턴(Singleton Pattern)생성 패턴(Creational Pattern) 중 하나로, 특정 클래스의 인스턴스가 오직 하나만 존재하도록 보장하고, 이 인스턴스에 전역적으로 접근할 수 있게 해주는 디자인 패턴이다. 하지만 위 패턴을 실무에 적용할때는 조금 조심해서 적용해야하는게 멀티스레드 환경에서는 예상치 못한 동기화 문제를 발생시키는 경우도 있으니 조심해서 적용하도록 하자.