Singleton Pattern

Mixer·2022년 12월 2일
0

디자인패턴 시리즈 첫 패턴 'Singleton Pattern'

싱글톤 패턴이란?
아주 단순하고 직관적인 이름을 가진 패턴이라고 생각이 든다.

소프트웨어 디자인 패턴에서 싱글턴 패턴(Singleton pattern)을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다. 이와 같은 디자인 유형을 싱글턴 패턴이라고 한다. 주로 공통된 객체를 여러개 생성해서 사용하는 DBCP(DataBase Connection Pool)와 같은 상황에서 많이 사용된다.
위키백과 싱글톤 패턴

객체의 인스턴스가 오직 1개만 생성되는 패턴으로 많이 정의가 되어있다.

또 누군가는 이렇게 설명했고 어플리케이션이 시작될 때 어떤 클래스가 최초 한번만 메모리를 할당하고(Static) 그 메모리에 인스턴스를 만들어 사용하는 패턴?

쉽게 싱글턴 패턴을 사용하면 쉽게 객체의 유일성을 보장할 수 있다?

전역 변수를 사용하지 않고 객체 하나만 생성 하도록 하며, 생성된 객체를 어디에서든지 참조할 수 있도록 하는 패턴?

놀랍게도 전부 다 해당하고 같은 싱글톤을 설명하고 결국 같은 결과를 말해주고 있다.

어떤 클래스의 인스턴스가 오직 하나임을 보장하고, 이 인스턴스에 접근할 수 있는 전역적인 접촉점을 제공하는 패턴

👉🏼 프로그램 시작부터 종료 할때까지 어떤 클래스의 인스턴스가 메모리 상에 단 하나만 존재할 수 있게 하고, 이 인스턴스에 대해 어디에서나 접근할 수 있도록 하는 패턴


public class Singleton

싱글톤 클래스라는 객체가 있다.

private Singleton() {}

이런식으로 하면 싱글톤 객체의 인스턴스를 아무도 사용할 수 없을 것이다.
그럼 자신을 멤버로 선언해서 메모리에 올려보면?

private static Singleton instance = new Singleton();

이 역시 멤버로 선언된 Singleton 클래스 역시 private

public static Singleton getInstance() {
	return instance;
    }

이렇게 하면 getInstance() Method 외에 Singleton 클래스 객체를 생성 및 사용할 수 없다.

public class Singleton {
	private static Singleton instance = new Singleton();
    
    private Singleton() {
    	// 생성자는 외부에서 호출하지 못하게 private 으로 지정해야 한다.
    }
    
    public static Singleton getInstance() {
    	return instance;
    }
    
    public void say() {
    	System.out.println("Hello there!");
    }
}

👉🏼싱글톤 패턴 구현 예제 게시글로 이동


사용하는 이유

  • 메모리
    최초 한번의 new 연산자를 통해 고정된 메모리 영역을 사용하기 때문에 추후 해당 객체에 접근할 때 메모리 낭비를 방지할 수 있으며 이미 생성된 인스턴스를 활용하니 속도 측면에서도 이점이 있다고 볼 수 있다.

  • 데이터 공유
    다른 클래스간의 데이터 공유가 쉽다
    싱글톤 인스턴스가 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있지만 여러 클래스의 인스턴스들이 싱글톤 인스턴스의 데이터에 동시에 접근하게 되면 동시성 문제가 발생할 수 있으니 유의하면 설계해야한다.

이 외에는 도메인 관점에서 인스턴스가 한 개만 존재할 수 있게 보증하고 싶은 경우 싱글톤 패턴을 사용하기도 한다.

문제점

  • 싱글톤 패턴을 구현하는 코드 자체가 많이 필요하다
    정적 팩토리 메서드에서 객체 생성을 확인하고 생성자를 호출하는 경우에 멀티스레딩 환경에서 발생할 수 있는 동시성 문제 해결을 위해 syncronized 키워드를 사용해야 한다.

  • 테스트의 어려움
    싱글톤 인스턴스는 자원을 공유하고 있기 때문에 테스트가 결정적으로 격리된 환경에서 수행되려면 매번 인스턴스의 상태를 초기화 시켜줘야 한다.
    만약 그렇지 않으면 어플리케이션 전역에서 상태를 공유하기 때문에 테스트가 온전히 수행되지 못한다.

  • 의존 관계상 클라이언트가 구체 클래스에 의존한다
    new 키워드를 직접 사용하여 클래스 안에서 객체를 생성하고 있으므로,
    SOLID 원칙 중 DIP를 위반하게 되고 OCP 원칙 또한 위반 가능성이 높다

  • 하위 클래스 생성 불가

  • 내부 상태 변경의 어려움

👉🏼 싱글톤 인스턴스가 너무 많은 일을 하거나 많은 데이터를 공유시킬 경우 다른 클래스의 인스턴스들 간의 결합도가 높아져 "개방 폐쇄 원칙" 위반

결국 싱글톤 패턴은 여러 문제를 갖고 있으며 유연성이 많이 떨어지는 패턴이라 설명이 된다.

단독으로 사용한다면 많은 원칙을 위반하는 사례가 발생하지만
스프링 컨테이너와 같은 프레임워크의 도움을 받으면 싱글톤 패턴의 문제점을 보완하면서 장점의 혜택을 누릴 수 있다.

한 게시글에 싱글톤 구현 등의 모든걸 작성하고 싶었지만, 글이 길어지면 가독성이 2배는 떨어지니 따로 작성해서 링크했습니다!


참고

https://tecoble.techcourse.co.kr/post/2020-11-07-singleton/
https://devmoony.tistory.com/43
https://gmlwjd9405.github.io/2018/07/06/singleton-pattern.html
https://blog.hexabrain.net/394
https://ynzu-dev.tistory.com/entry/JAVA-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4Singleton-Pattern-%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C%EC%9D%98-%EB%AC%B8%EC%A0%9C%EC%A0%90
profile
Minthug'life

0개의 댓글