# 싱글톤 패턴

싱글톤 패턴 작성 예

```java
package hello.core.singleton;

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

싱글톤 패턴 테스트 코드 예시

```java
@Test
@DisplayName("싱글톤 패턴 적용한 객체 사용")
void singletonServiceTest(){
    SingletonService instance1 = SingletonService.getInstance();
    SingletonService instance2 = SingletonService.getInstance();
    System.out.println("instance1 = " + instance1);
    System.out.println("instance2 = " + instance2);
    //인스턴스가 같은지 비교하기위해 isSameAs 사용한다!
    assertThat(instance1).isSameAs(instance2);
    //same == : 객체 인스턴스가 같은지 참조값을 비교.
    //equal : 자바의 equals
}
```

1. instance 하나 먼저 생성
2. 1의 instance 반환하는 getInstance() 메서드 생성
3. 1의 instance 생성자는 private으로 외부 생성 막는다.

설명

1. JVM 실행되면 SingletonService 자기 자신을 내부에 private static으로 생성해서 instance 안에 참조를 넣는다!\
   \=>이렇게 static으로 하면 클래스 래밸에 올라가므로 딱 하나만 존재하게 된다!
2. instance를 꺼낼 수 있는 방법은 getInstance() 밖에 없다.
3. instance를 생성할 수 있는 방법도 없다! private으로 막아버렸기 때문.\
   \=> instance는 딱 하나만 존재할 수 있게 된다!

싱글톤 패턴의 장점과 단점

장점 : 싱글톤 패턴을 적용하면 고객의 요청이 올 때 마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유해서 효율적으로 사용할 수 있다. 하지만 싱글톤 패턴은 다음과 같은 수 많은 문제점들을 가지고 있다.

싱글톤 패턴 문제점

* 싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다.
* 의존관계상 클라이언트가 구체 클래스에 의존한다. =>DIP를 위반한다!

```java
@Configuration
public class AppConfig{
    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());//객체 생성하고 구현체 할당하는 것을 안에서 직접했었다.
    }
```

기존의 memberService 빈을 싱글톤으로 바꾸면 MemberServiceImpl.getIntance() 이렇게 된다고 한다. 이것은 클라이언트가 구체클래스에 접근(의존)하고 있는 것이므로 DIP(의존 역전 원칙) 위반이다! 이렇게 되면 이것은 OCP(개방 폐쇠 원칙)위반으로 이어질 수 있다!

* 클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높다.
* 테스트하기 어렵다.&#x20;
* 내부 속성을 변경하거나 초기화 하기 어렵다.&#x20;
* private 생성자로 자식 클래스를 만들기 어렵다.&#x20;
* 결론적으로 유연성이 떨어진다.&#x20;
* 안티패턴으로 불리기도 한다.
