자바 OOP

자바 Singleton Pattern(싱글톤 패턴)이란?

chadongmin 2023. 5. 17. 14:51

싱글톤 패턴이란

Gang of Four 디자인패턴 중 생성패턴 중의 한 종류입니다.
프로그램에서 인스턴스가 단 하나만 생성되어야 하는 경우 사용되는 디자인패턴입니다.

자바에서 싱글톤 패턴을 사용하는 예제입니다.

package ch0516_SingletonPattern;

public class Student {
    private static Student INSTANCE = new Student();

    private Student(){}

    public static Student getInstance(){
        return INSTANCE;
    }
}

INSTANCE라는 멤버변수를 private static으로 new 키워드를 통해 생성합니다.

그리고 기본 생성자를 private으로 선언해서 외부에서 접근할 수 없도록 합니다.

그리고 getInstance라는 메소드를 만들어서 INSTANCE를 리턴합니다.

 

그러면 외부에서 Student 클래스를 참조하고 싶을 때는 getInstance 메소드를 통해 리턴받은 INSTANCE를 통해서만 접근이 가능합니다.

 

package ch0516_SingletonPattern;

public class Company {
    private static Company INSTANCE;
    static{
        INSTANCE = new Company();
    }

    private String name;

    private Company(){} //외부에서 쓰지 못하게 기본 생성자 private으로 선언

    public static Company getInstance(){
        return INSTANCE;
    }

    @Override
    public String toString() {
        return "Company{" +
                "name='" + name + '\'' +
                '}';
    }

    public void setName(String name){
        this.name = name;
    }

}

class AppMain{
    public static void main(String[] args) {
        Company company1 = Company.getInstance();
        Company company2 = Company.getInstance(); //company1과 company2가 같은 메모리 주소를 바라보고 있다. call by reference!

        System.out.println(company1.hashCode());
        System.out.println(company2.hashCode());
    }
}

위 예제와 같이 static 코드 블럭을 이용해서 Instance를 생성할 수도 있습니다.

이렇게 만들어진 company1과 company2 인스턴스는 

같은 메모리 주소값을 가지게 됩니다.

 

싱글톤 패턴을 통해 단 하나의 인스턴스만 가지기 떄문입니다!

 

 

하지만 싱글톤패턴도 멀티스레드 환경에서는 인스턴스가 2개가 생길 수 있다는 단점을 가지고 있습니다.

 

보통의 싱글톤 패턴은 if 문을 사용하여 INSTACE가 null 이라는 조건을 만족시킬때만 new 생성자로 만들어진 INSTANCE를 리턴하도록 설계되는데, 두 스레드가 동시에 접근할때는 인스턴스가 두 개가 생기는 일이 생길 수도 있습니다. 

 

이러한 문제를 해결하기 위해서 synchronized 키워드를 붙여서 lock을 거는 방식이 있습니다. 하지만 이 방법은 성능을 저하시킨다는 단점이 존재합니다.

 

또 다른 방법은 이 게시글 상단에 제가 작성한 static으로 작성하는 방식이 있습니다. static 키워드를 사용하면 힙 메모리가 아닌 stack에 소스코드가 실행되는 즉시 인스턴스가 생성됩니다. 하지만 이 방식은 싱글톤 인스턴스가 필요하지 않은 로직을 수행하는 경우에도 클래스를 로딩할때 인스턴스가 생성되기 때문에 불필요한 자원을 낭비한다는 단점이 있습니다.