본문 바로가기
Java

싱글턴 패턴 (Singleton pattern) 이란?

by 승화니' 2021. 5. 5.

싱글턴 패턴 (Singleton pattern)

 

싱글톤패턴 : 어떤 클래스에서 호출해도 하나의 인스턴스만 호출

 

어떤 클래스가 최초 한 번만 메모리를 할당하고(Static) 그 메모리에 인스턴스를 만들어서 사용하는 디자인 패턴이다.

생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나고 최초 생성 이후에 호출된 생성자는 최초에 생성한 객체를 반환한다.

 

쉽게 말해.. Singleton 패턴은 어떠한 클래스가 유일하게 1개만 존재할 때 사용된다.

이를 주로 사용하는 곳은 서로 자원을 공유할 때 사용하는데, 현실 세계에서는 프린터가 해당되며, 실제 프로그 래핑에서는 TCP Socket 통신에서 서버와 연결된 connect 객체에 주로 사용한다.

 

 

아래의 예제는 어떠한 서버와 통신을 한다 했을 때 매번 통신하는 게 아니라 한번 연결해놨던 connect 통로를 통해 사용하는 것 을 예제를 다뤄 보겠다.

 

public class SocketClient {

    private static SocketClient socketClient = null;

    private SocketClient() {}

    public static SocketClient getInstance() {
        if (socketClient == null)
            socketClient = new SocketClient();

        return socketClient;
    }

}

 

Singleton 패턴이라는 것은 기본적으로 자기 자신에 객체로 가지고 있어야 하고, 기본 생성자는 기본 생성자로 생성할 수 없도록 private으로 지정합니다.

 

그다음 어떠한 클래스에서도 바로 사용할 수 있도록 static 메서드를 통해 getInstance()를 제공해야 하고, getInstance()는 객체 자기 자신을 return 할 수 있도록 자료형은 SocketClient으로 지정합니다.

 

getInstance()에서 socketClient객체를 가지고 있는지 없는지 를 판단하기 위해 if문을 두어 socketClient가 null이면 객체를 생성하고 객체가 있으면 다시 생성하지 않고 바로 자신이 가지고 있는 객체를 return 될 수 있도록 최초에 한 번만 생성할 수 있도록 만들어 주었습니다.

 

 

SocketClient 객체를 사용하는 아래와 같은 두 가지(AClass, BClass) 객체를 만들어 보겠습니다.

 

public class AClass {

    private SocketClient socketClient;

    public AClass() {
        this.socketClient = SocketClient.getInstance();
    }

    public SocketClient getSocketClient() {
        return this.socketClient;
    }

}

 

public class BClass {

    private SocketClient socketClient;

    public BClass() {
        this.socketClient = SocketClient.getInstance();
    }

    public SocketClient getSocketClient() {
        return this.socketClient;
    }

}

 

SocketClient 객체의. getInstance()를 가져오는 AClass, BClass 내용은 같습니다.

 

각 객체의 생성자를 보면 SocketClient 객체의 getInstance()를 불러와 멤버 변수에 할당해 주고, getSocketClient()는 각 AClass, BClass 객체의 멤버 변수에 할당된 인스턴스를 불러오는 역할로 사용됩니다.

 

 

여기까지 완성이 되었으니 main 메서드를 만들어 테스트를 해봅시다.

 

public class Main {

    public static void main(String[] args) {

        AClass aClass = new AClass();
        BClass bClass = new BClass();

        SocketClient aClient = aClass.getSocketClient();
        SocketClient bClient = bClass.getSocketClient();

        System.out.println(aClient.equals(bClient));

    }
}

 

main 메서드 안에 있는 new AClass(); 와 new BClass(); 여기까지 내용만 보서 보면 서로 다른 객체입니다. 하지만 싱글턴 방식의 패턴으로 서로 같은 getSocketClient 인지 확인해 보면 결과는 어떻까??

 

System.out.println(aClient.equals(bClient)); 의 결과

결과는 true 가 나오게 됩니다.

 

반대로 false 가 나오게 하려면, SocketClient Class의 생성자는 private에서 public으로 변경해줍니다.

그리고 AClass, BClass 생성자에 직접 SocketClient객체를 생성할 수 있도록 new SocketClient(); 를 달아 멤버 변수에 할당해서 다시 main 메서드에 돌아가 테스트해 보면 false가 나오게 됩니다.

 

이렇듯. 어떤 환경에서 1개의 객체만 존재해야 한다면 위와 같은 싱글턴 패턴 방식을 이용하시면 됩니다.

위와 관련된 코드는
https://github.com/lsh955/java_design_pattern/tree/master/src/com/company/design/singleton 에서 확인하실 수 있습니다.
 

lsh955/java_design_pattern

Contribute to lsh955/java_design_pattern development by creating an account on GitHub.

github.com

 

그러면 Spring (스프링)에서의 싱글턴 패턴은 어떻까?

 

스프링 싱글은 클래스 자체에 의해서가 아니라, 스프링 컨테이너(Bean Factory/Application Context)에 의해 구현된다.

 

스프링에서는, 컨테이너 내에서 특정 클래스에 대해 @Bean이 정의되면, 스프링 컨테이너는 그 클래스에 대해 딱 한 개의 인스턴스를 만든다. 공유 인스턴스는 설정 정보에 의해 관리되고, bean이 호출될 때마다 스프링은 생성된 공유 인스턴스를 return 시킨다. 

 

Spring Singleton 

공유 인스턴스의 생성시점은 스프링 컨테이너에 따라 달라지는데, Bean팩토리 최초 호출 시점에서 인스턴스를 생성하고(Lazy loading), 애플리케이션 콘텍스트는 미리 모든 공유 인스턴스를 다 초기화해 두었다가 호출될 때 바로 return 시켜준다. 

'Java' 카테고리의 다른 글

옵저버 패턴 (Observer pattern) 이란?  (0) 2021.05.23
어댑터 패턴 (Adapter pattern) 이란?  (2) 2021.05.19

댓글