앞서 있었던 문제를 싱글톤 패턴을 이용하여 해결하는 시간을 가졌다.

 

싱글톤 패턴?

 

클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.

그래스 객체 인스턴스를 2개 이상 생성하지 못하도록 막아야한다.

-private 생성자를 사용하여 외부에서 임의로 new 키워드를 사용하지 못하도록 막아야한다.

 

package hello.core.singleton;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class SingletonService {

    private static final SingletonService instance = new SingletonService();
    
    public static SingletonService getInstance(){
        return instance;
    }
    
    private SingletonService(){
        
    }
    
    public void logic(){
        System.out.println("싱글톤 객체 로직 호출");
    }
   
}

1. static 영역에 객체 instance를 미리 하나 생성하여 올려둔다.

2. 이 객체 인스턴스가 필요하면 오직 getInstance() 메서드를 통해서면 조회할 수 있다. 이 메서드를 호출하면

항상 같은 인스턴스를 반환한다.

3. 딱 1개의 객체 인스턴스만 존재해야 하므로, 생성자를 private으로 막아서 혹시라도 외부에서 new 키워드로 객체 인스턴스가

생성되는 것을 막는다.

    @Test
    @DisplayName("싱글톤 패턴을 적용한 객체 사용")
    void singletonServiceTest(){
        SingletonService singletonService1 = SingletonService.getInstance();
        SingletonService singletonService2 = SingletonService.getInstance();

        System.out.println("singletonService1 = " + singletonService1);
        System.out.println("singletonService2 = " + singletonService2);

        assertThat(singletonService1).isSameAs(singletonService2);
    }

테스트 코드로 확인해보았다.

isSameAs : 메모리상 같은 객체를 가리키는지 비교 (주소 비교)
isEqualTo : 객체가 같은 값을 가지고 있는지 비교한다.

같은 인스턴스를 참조하는 것을 확인할 수 있었다.

 

그렇다면? AppConfig를

싱글톤으로 바꾸어어서 getInstance로 반환하면 된다고 생각했는데

그렇게 할 필요가 없었다. 

스프링 컨테이너를 사용하면 스프링 컨테이너가

객체를 싱글톤으로 관리해준다.

 

싱글톤 패턴을 적용하면 고객의 요청이 올때마다 객체를 생성하는 것이 아니라,

이미 만들어진 객체를 공유해서 효율적으로 사용 할 수 있다. 하지만 싱글톤 패턴은 

수 많은 문제점들을 가지고 있다.

 

{

싱글톤 패턴을 구현하는 코드 자체가 많이들어간다.

 

의존관계상 클라이언트가 구체 클래스에 의존한다. -> DIP위반

 

클라이언트가 구체 클래스에 의존해서  OCP원칙을 위반할 가능성이 높다.

 

테스트 하기가 어렵다

 

내부 속성을 변경하거나 초기화하기 어렵다.

 

private생성자로 자식 클래스를 만들기 어렵다.

 

결론적으로 유연성이 떨어진다.

 

안티패턴으로 불리기도한다.

}

+ Recent posts