저번 주에 코드리뷰를 하면서 getInstance()로 클래스 인스턴스를 사용한 분을 봤는데,
이게 뭔가 찾아봤더니 싱글톤 패턴이더라고요
저도 싱글톤 패턴을 적용해보고 싶어서 이번 과제에 이곳저곳 썼답니다.
하지만 이렇게 하다 보니 객체 지향 설계가 깨지는 것 같아 이를 해결해보고자 공부했던 내용입니다

new 키워드 사용public Class LottoService{
private final Lotto lotto = new Lotto();
}

사용 이유
- 메모리 낭비 방지
- 처음에 한번 생성한 고정된 메모리 영역 사용
- 데이터 공유가 쉬움 ( 하나의 인스턴스를 여러 곳에서 사용하기 때문에)
⇒ 인스턴스가 단 하나만 필요하거나, 여러 객체에 걸쳐 상태를 공유해야 할 때 유용
문제점
- 코드 자체가 많이 필요함
- 정적 팩토리 메서드에 객체 생성을 확인하고 생성자를 호출하는 경우
⇒ 동시성 문제 해결 위해syncronized키워드를 사용- 테스트가 어려움
- 싱글톤 인스턴스는 전역 상태, 즉 자원을 공유하고 있음
- 독립적인 테스트를 수행하려면 매번 인스턴스 상태를 초기화 해줘야함
- 의존성이 높아짐
- new 클래스를 직접 사용하여 클래스 안에서 객체 생성 → 당연히 구체 클래스에 의존할 수 밖에 …
- 다른 클래스로 바꾸고 싶으면? 직접 하나하나 찾아서 수정
// LottoService Class
public Class LottoService{
private final Lotto lotto;
public LottoService(){
this.lotto = Lotto.getInstance();
}
}
// Lotto class
public Class Lotto{
private static final Lotto INSTANCE= new Lotto();
private Lotto(){};
public static Lotto getInstance() {
return INSTANCE;
}
}
💡 각각의 장단점이 있지만 이 친구들은 객체지향 원칙에 위배되네요!
객체지향 원칙을 따르려면 의존성 주입이 필요합니다
소프트웨어는 기본적으로 2가지 영역으로 구분됌
메인 영역은 어플리케이션 영역의 객체를 생성, 설정, 실행하는 총 책임을 가짐
→ 어플리케이션 영역에서 사용할 하위 수준의 모듈을 변경하고 싶다면 메인 영역을 수정해야함
→ 어떻게? DI, 서비스 로케이터로!
생성자 주입 (Constructor Injection)
public class LottoStatistics {
private final LottoService lottoService;
@Autowired
public LottoStatistics(LottoService lottoService) {
this.lottoService = lottoService;
}
}
setter 주입 (Setter Injection)
public class LottoStatistics {
private LottoService lottoService;
public void setLottoService(LottoService lottoService) {
this.lottoService = lottoService;
}
}
필드 주입 (Field Injection)
public class LottoStatistics {
@Autowired
private LottoService lottoService;
}

public class ServiceLocator {
private static final LottoService lottoService = new LottoService();
public static LottoService getLottoService() {
return lottoService;
}
}
public class LottoStatistics {
private final LottoService lottoService = ServiceLocator.getLottoService();
}