싱글 톤이 나쁘다면 어떻게해야할까요? 화면과 구성 요소가

최근 싱글 톤 사용 (과용) 문제에 대해 많은 논의가있었습니다. 나는 내 경력 초기에 그 사람들 중 하나였습니다. 나는 지금 문제가 무엇인지 알 수 있지만, 여전히 좋은 대안을 찾을 수없는 경우가 많지만, 많은 안티 싱글 톤 토론이 실제로 하나를 제공하지는 않습니다.

다음은 제가 최근에 참여한 주요 프로젝트의 실제 예입니다.

응용 프로그램은 너무 자주 업데이트되지 않는 서버 상태에서 많은 양의 데이터를 사용하는 별도의 화면과 구성 요소가 많은 씩 클라이언트였습니다. 이 데이터는 기본적으로 단일 “관리자”개체 (두려운 “전역 상태”)에 캐시되었습니다. 아이디어는 데이터를 저장하고 동기화하는 앱에이 장소를 두는 것이 었으며, 열린 새 화면은 서버에서 다양한 지원 데이터를 반복적으로 요청하지 않고도 필요한 부분을 대부분 쿼리 할 수 ​​있습니다. 끊임없이 서버에 요청하면 너무 많은 대역폭이 필요합니다. 일주일에 수천 달러의 추가 인터넷 요금을 청구하고 있기 때문에 받아 들일 수 없었습니다.

기본적으로 이런 종류의 전역 데이터 관리자 캐시 개체를 갖는 것보다 여기에 적절한 다른 접근 방법이 있습니까? 이 객체는 공식적으로 “싱글 톤”일 필요는 없지만 개념적으로는 하나의 의미가 있습니다. 좋은 깨끗한 대안은 무엇입니까?



답변

여기서 단일 인스턴스Singleton 디자인 패턴 을 구분하는 것이 중요합니다 .

단일 인스턴스 는 단순히 현실입니다. 대부분의 앱은 한 번에 하나의 구성, 한 번에 하나의 UI, 한 번에 하나의 파일 시스템 등 만 작동하도록 설계되었습니다. 유지해야 할 상태 나 데이터가 많으면 확실히 하나의 인스턴스 만 갖고 가능한 한 오래 유지해야합니다.

싱글 톤 디자인 패턴 은 매우 특정한 유형 의 단일 인스턴스, 특히 다음과 같은 유형 입니다.

  • 전역 정적 인스턴스 필드를 통해 액세스 할 수 있습니다.
  • 프로그램 초기화 또는 최초 액세스시 작성됩니다.
  • 공개 생성자가 없습니다 (직접 인스턴스화 할 수 없음).
  • 명시 적으로 해제하지 마십시오 (프로그램 종료시 암시 적으로 해제).

이 특정 설계 선택으로 인해 패턴에 몇 가지 잠재적 인 장기 문제가 발생합니다.

  • 추상 또는 인터페이스 클래스를 사용할 수 없음
  • 서브 클래스 불가능
  • 응용 분야에서 높은 결합 (수정하기 어려움)
  • 테스트하기 어려움 (단위 테스트에서 위조 / 조롱 할 수 없음);
  • 변경 가능한 상태의 경우 병렬화하기 어려움 (광범위한 잠금이 필요함);
  • 등등.

이 증상들 중 어느 것도 실제로 단일 인스턴스에만 해당되는 것이 아니라 싱글 톤 패턴 일뿐입니다.

대신 무엇을 할 수 있습니까? 싱글 톤 패턴을 사용하지 마십시오.

질문에서 인용 :

아이디어는 데이터를 저장하고 동기화하는 앱에이 장소를 두는 것이 었으며, 열린 새 화면은 서버에서 다양한 지원 데이터를 반복적으로 요청하지 않고도 필요한 부분을 대부분 쿼리 할 수 ​​있습니다. 끊임없이 서버에 요청하면 너무 많은 대역폭이 필요합니다. 일주일에 수천 달러의 추가 인터넷 요금을 청구하고 있기 때문에 받아 들일 수 없었습니다.

이 개념에는 힌트가 있지만 확실하지 않은 이름이 있습니다. 이것을 캐시 라고 합니다 . 화려하고 싶다면 “오프라인 캐시”또는 원격 데이터의 오프라인 복사본이라고 부를 수 있습니다.

캐시는 싱글 톤일 필요는 없습니다. 그것은 여러 캐시 인스턴스에 대한 동일한 데이터를 가져 오는 피하려는 경우 하나의 인스턴스가 필요; 그렇다고해서 실제로 모든 사람에게 모든 것을 노출 시켜야한다는 의미는 아닙니다 .

가장 먼저 할 일은 캐시 의 다른 기능 영역 을 별도의 인터페이스로 분리하는 것입니다. 예를 들어 Microsoft Access를 기반으로 세계에서 가장 최악의 YouTube 복제본을 만들고 있다고 가정 해 보겠습니다.

                          MSAccessCache
                                ▲
                                |
              + ----------------- + ----------------- +
              | | |
         IMediaCache IProfileCache IPageCache
              | | |
              | | |
          VideoPage MyAccountPage MostPopularPage

여기에는 미디어, 사용자 프로필 및 정적 페이지 (예 : 프론트 페이지)와 같이 특정 클래스가 액세스해야하는 특정 유형의 데이터를 설명하는 몇 가지 인터페이스 가 있습니다. 이 모든 것은 하나의 메가 캐시 로 구현 되지만 대신 인터페이스를 허용하도록 개별 클래스를 설계하므로 인스턴스의 종류에 상관하지 않습니다. 프로그램이 시작될 때 실제 인스턴스를 한 번 초기화 한 다음 생성자와 공용 속성을 통해 인스턴스를 특정 인터페이스 유형으로 캐스트하기 시작하면됩니다.

그건 그렇고, 의존성 주입 이라고 합니다; 일반 클래스 디자인 이 호출자로부터 자신인스턴스를 인스턴스화 하거나 전역 상태를 참조 하는 대신 호출자의 종속성을 허용 하는 한 Spring 또는 특수 IoC 컨테이너를 사용할 필요가 없습니다 .

왜 인터페이스 기반 디자인을 사용해야합니까? 세 가지 이유 :

  1. 코드를보다 쉽게 ​​읽을 수 있습니다. 인터페이스 에서 종속 클래스가 의존 하는 데이터를 정확하게 이해할 수 있습니다 .

  2. Microsoft Access가 데이터 백엔드에 가장 적합하지 않다는 것을 알게되면 SQL Server라고하겠습니다.

  3. SQL Server가 미디어에 특히 적합하지 않다는 것을 알고 있다면 시스템의 다른 부분에 영향을주지 않고 구현 중단 할 수 있습니다 . 그것이 바로 추상 추상화의 힘이 들어오는 곳입니다.

한 걸음 더 나아가려면 Spring (Java) 또는 Unity (.NET)와 같은 IoC 컨테이너 (DI 프레임 워크)를 사용할 수 있습니다. 거의 모든 DI 프레임 워크는 자체 수명 관리를 수행하며 특정 서비스 를 단일 인스턴스로 정의 할 수 있습니다 (종종 “싱글 톤”이라고 부르지 만 이는 친숙 함을위한 것입니다). 기본적으로 이러한 프레임 워크는 인스턴스를 수동으로 전달하는 원숭이 작업의 대부분을 저장하지만 반드시 필요한 것은 아닙니다. 이 디자인을 구현하기 위해 특별한 도구가 필요하지 않습니다.

완벽을 기하기 위해 위의 디자인도 이상적이지 않다는 점을 지적해야합니다. 캐시를 처리 할 때 (있는 그대로) 실제로 완전히 별도의 레이어 가 있어야합니다 . 다시 말해, 이와 같은 디자인 :

                                                        +-IMediaRepository
                                                        |
                          캐시 (일반) --------------- +-IProfileRepository
                                ▲ |
                                | +-IPageRepository
              + ----------------- + ----------------- +
              | | |
         IMediaCache IProfileCache IPageCache
              | | |
              | | |
          VideoPage MyAccountPage MostPopularPage

이것의 장점은 Cache리팩토링하기로 결정한 경우 인스턴스 를 해체 할 필요가 없다는 것입니다 . 대체 구현을 제공하여 미디어가 저장되는 방식을 간단하게 변경할 수 있습니다 IMediaRepository. 이것이 어떻게 결합되는지에 대해 생각하면 캐시의 물리적 인스턴스를 하나만 작성하므로 동일한 데이터를 두 번 가져올 필요가 없습니다.

세계의 모든 단일 소프트웨어가 높은 응집력과 느슨한 결합의 정확한 표준에 맞게 설계 될 필요는 없습니다. 프로젝트의 규모와 범위, 팀, 예산, 마감일 등에 따라 달라집니다. 그러나 최상의 디자인이 무엇인지 (단일 대신 사용) 요구하는 경우에는 이것이됩니다.

추신 다른 사람들이 언급했듯이 종속 클래스가 캐시를 사용하고 있다는 것을 인식하는 것이 가장 좋은 아이디어는 아닙니다. 즉, 결코 신경 쓰지 않아야하는 구현 세부 사항입니다. 즉, 전체 아키텍처는 여전히 위의 그림과 매우 유사하게 보일 것 입니다. 개별 인터페이스를 Caches 라고 부르지 는 않습니다 . 대신 서비스 또는 이와 유사한 이름을 지정하십시오 .


답변

당신이주는 경우, 싱글 톤을 사용하는 것이 문제가 아니라 문제의 증상 -더 큰 구조적 문제 인 것처럼 들립니다 .

화면에서 캐시 개체에 데이터를 쿼리하는 이유는 무엇입니까? 캐싱은 클라이언트에게 투명해야합니다. 데이터를 제공하기위한 적절한 추상화가 있어야하며, 추상화의 구현은 캐싱을 활용할 수 있습니다.

문제는 시스템 부분 간의 종속성이 올바르게 설정되지 않았을 가능성이 높으며 이는 아마도 체계적인 것일 수 있습니다.

화면이 데이터를 얻는 위치를 알아야하는 이유는 무엇입니까? 화면에 데이터 요청을 수행 할 수있는 객체가 제공되지 않는 이유는 무엇입니까 (캐시가 숨겨져 있음)? 종종 화면 작성에 대한 책임이 중앙 집중식이 아니므로 종속성을 주입 할 명확한 시점이 없습니다.

다시, 우리는 대규모 건축 및 디자인 문제를 검토하고 있습니다.

또한 객체 의 수명 이 객체의 사용 방법과 완전히 분리 될 수 있음 을 이해하는 것이 매우 중요 합니다.

캐시는 응용 프로그램의 수명 동안 유용해야하며 (유용하기 위해) 개체의 수명은 싱글 톤의 수명입니다.

그러나 Singleton (적어도 정적 클래스 / 속성으로 Singleton의 일반적인 구현)의 문제는 그것을 사용하는 다른 클래스가 찾는 방법입니다.

정적 Singleton 구현의 경우 규칙은 필요할 때마다이를 사용하는 것입니다. 그러나 그것은 의존성을 완전히 숨기고 두 클래스를 밀접하게 결합시킵니다.

우리 가 클래스에 대한 의존성을 제공 한다면 , 그 의존성은 명백하고 소비하는 모든 클래스가 사용할 수있는 계약에 대해 알아야합니다.


답변

나는 이 질문에 대한 전체 장 을 썼습니다 . 대부분 게임의 맥락에서 볼 수 있지만 대부분 게임 외부에 적용해야합니다.

tl; dr :

Gang of Four Singleton 패턴은 두 가지 작업을 수행합니다. 어느 곳에서나 객체에 편리하게 액세스 할 수 있으며 하나의 인스턴스 만 만들 수 있습니다. 시간의 99 %, 당신이 걱정하는 것은 그것의 상반기이며, 후반을 따라 카트를 타면 불필요한 제한이 추가됩니다.

뿐만 아니라 편리한 액세스를 제공하는 더 나은 솔루션이 있습니다. 객체를 전역으로 만드는 것은이를 해결하기위한 핵 옵션이며 캡슐화를 쉽게 파괴 할 수있는 방법입니다. 글로벌에 대해 나쁜 모든 것은 싱글 톤에 완전히 적용됩니다.

동일한 객체를 터치해야하는 코드가 많이 있기 때문에 사용하는 경우 전체 코드베이스에 노출시키지 않고 해당 객체 에만 더 좋은 방법을 찾아보십시오 . 다른 솔루션 :

  • 완전히 버리십시오. 나는 상태가 없으며 헬퍼 함수의 가방 인 많은 싱글 톤 클래스를 보았습니다. 그것들은 전혀 인스턴스가 필요하지 않습니다. 정적 함수로 만들거나 함수가 인수로 사용하는 클래스 중 하나로 이동하십시오. Math할 수 있다면 특별한 수업이 필요 하지 않습니다 123.Abs().

  • 통과시켜 메소드에 다른 객체가 필요한 경우 간단한 해결책은 그냥 전달하는 것입니다. 일부 객체를 전달하는 데 아무런 문제가 없습니다.

  • 기본 수업에 넣습니다. 모든 특수 객체에 액세스해야하는 클래스가 많고 기본 클래스를 공유하는 경우 해당 객체를베이스의 멤버로 만들 수 있습니다. 그것을 만들 때 객체를 전달하십시오. 이제 파생 된 객체는 필요할 때 얻을 수 있습니다. 보호하면 개체가 계속 캡슐화 된 상태로 유지됩니다.


답변

그 자체가 문제인 글로벌 상태는 아닙니다.

정말 걱정할 필요가 있습니다 global mutable state. 일정한 상태는 부수적 인 영향을받지 않으므로 문제가 적습니다.

싱글 톤의 주요 관심사는 커플 링을 추가하여 테스트와 같은 것을 어렵게 만든다는 것입니다. 다른 소스 (예 : 공장)에서 싱글 톤을 가져와 커플 링을 줄일 수 있습니다. 이렇게하면 특정 인스턴스에서 코드를 분리 할 수 ​​있습니다 (공장에 더 연결되어 있지만 적어도 공장은 다른 단계에 대한 대체 구현을 가질 수 있음).

귀하의 상황에서 싱글 톤이 실제로 인터페이스를 구현하는 한 (다른 상황에서 대안을 사용할 수있는 한) 벗어날 수 있다고 생각합니다.

그러나 싱글 톤의 또 다른 주요 단점은 일단 코드에서 코드를 제거하고 다른 것으로 대체하면 실제로 어려운 작업이된다는 것입니다 (다시 결합해야 함).

// Example from 5 minutes (con't be too critical)
class ServerFactory
{
    public:
        // By default return a RealServer
        ServerInterface& getServer();

        // Set a non default server:
        void setServer(ServerInterface& server);
};

class ServerInterface { /* define Interface */ };

class RealServer: public ServerInterface {}; // This is a singleton (potentially)

class TestServer: public ServerInterface {}; // This need not be.


답변

그리고 뭐? 아무도 말하지 않았기 때문에 : Toolbox . 전역 변수 가 필요한 경우 입니다.

다른 각도에서 문제를 살펴보면 싱글 톤 남용 을 피할 수 있습니다. 응용 프로그램에 클래스의 인스턴스가 하나만 필요하고 응용 프로그램이 시작시 해당 클래스를 구성한다고 가정 해 봅시다. 클래스 자체가 단일 클래스를 담당해야하는 이유는 무엇입니까? 응용 프로그램에 이러한 종류의 동작이 필요하기 때문에 응용 프로그램에서이 책임을 맡는 것이 상당히 논리적 인 것 같습니다. 구성 요소가 아닌 응용 프로그램은 싱글 톤이어야합니다. 그런 다음 응용 프로그램은 구성 요소의 인스턴스를 응용 프로그램 별 코드에서 사용할 수있게합니다. 응용 프로그램에서 이러한 구성 요소를 여러 개 사용하면 도구 상자라는 구성 요소로 집계 할 수 있습니다.

간단히 말해서, 응용 프로그램의 도구 상자는 자체 구성 또는 응용 프로그램의 시작 메커니즘으로 구성 할 수있는 단일 요소입니다 …

public class Toolbox {
     private static Toolbox _instance;

     public static Toolbox Instance {
         get {
             if (_instance == null) {
                 _instance = new Toolbox();
             }
             return _instance;
         }
     }

     protected Toolbox() {
         Initialize();
     }

     protected void Initialize() {
         // Your code here
     }

     private MyComponent _myComponent;

     public MyComponent MyComponent() {
         get {
             return _myComponent();
         }
     }
     ...

     // Optional: standard extension allowing
     // runtime registration of global objects.
     private Map components;

     public Object GetComponent (String componentName) {
         return components.Get(componentName);
     }

     public void RegisterComponent(String componentName, Object component)
     {
         components.Put(componentName, component);
     }

     public void DeregisterComponent(String componentName) {
         components.Remove(componentName);
     }

}

하지만 그거 알아? 싱글 톤입니다!

그리고 싱글 톤은 무엇입니까?

어쩌면 그것은 혼란이 시작되는 곳입니다.

나에게 싱글 톤 은 항상 단일 인스턴스 만 갖도록 강요 된 객체입니다. 인스턴스화 할 필요없이 언제 어디서나 액세스 할 수 있습니다. 이것이와 밀접한 관련이있는 이유 static입니다. 비교를 static위해 인스턴스가 아닌 것을 제외하고는 기본적으로 동일합니다. 우리는 그것을 자동으로 할당하기 때문에 인스턴스화 할 필요가 없습니다. 그리고 그것은 문제를 일으킬 수 있습니다.

내 경험상 staticSingleton을 간단히 교체하면 내가 사용 하고있는 중간 크기의 패치 워크 백 프로젝트에서 많은 문제가 해결되었습니다. 그것은 나쁜 디자인 프로젝트에 약간의 사용법이 있다는 것을 의미합니다. 너무 많이 있다고 생각 논의 경우 싱글 톤 패턴 입니다 유용 여부 그것은 실제로 있다면 정말 주장 할 수없는 나쁜 . 그러나 여전히 정적 방법보다 싱글 톤에 유리한 좋은 주장 이 여전히 있습니다 .

내가 확신하는 유일한 것은 싱글 톤에 대해 나쁜 것입니다. 좋은 습관을 무시하면서 싱글 톤을 사용할 때입니다. 그것은 실제로 다루기가 쉽지 않은 것입니다. 그러나 모든 패턴에 나쁜 관행을 적용 할 수 있습니다. 그리고, 나는 그것을 말하기에는 너무 일반적입니다 … 나는 그것에 너무 많은 것이 있다는 것을 의미합니다.

내가 틀리지 마!

간단히 말해,처럼 글로벌 바르 , 싱글은해야 여전히 항상 피할 수 . 특히 그들이 남용되기 때문에. 그러나 전역 변수를 항상 피할 수는 없으며 마지막 경우에 사용해야합니다.

어쨌든, 도구 상자 이외에 다른 많은 제안이 있으며 도구 상자와 마찬가지로 각 도구에는 응용 프로그램이 있습니다 …

다른 대안들

  • 난 그냥 싱글에 대해 읽은 최고의 기사는 제안 서비스 로케이터를 대안으로. 나에게 그것은 기본적으로 ” 정적 도구 상자 “입니다. 다시 말해, 서비스 로케이터를 싱글 톤으로 만들면 도구 상자가 있습니다. 그것은 물론 싱글 톤을 피하겠다는 최초의 제안과 반대되지만, 싱글 톤의 문제를 강제하는 것은 패턴 자체가 아니라 그것이 어떻게 사용되는지에 달려 있습니다.

  • 다른 사람들공장 패턴 을 대안으로 제안 합니다. 그것은 동료로부터 들었던 첫 번째 대안이었고 우리는 전역 변수 로 사용하기 위해 신속하게 제거했습니다 . 물론 사용법도 있지만 싱글 톤도 마찬가지입니다.

위의 두 가지 대안 모두 좋은 대안입니다. 그러나 그것은 모두 당신의 사용법에 달려 있습니다.

이제 모든 비용으로 싱글 톤을 피해야한다는 것은 잘못된 것입니다 …

  • Aaronaught 의 대답은 여러 가지 이유로 싱글 톤을 사용하지 말 것을 제안하고 있습니다 . 그러나 그것들은 패턴 자체에 직접적으로 영향을 미치지 않고, 악용되고 악용되는 방식에 대한 모든 이유입니다. 나는 그 점에 대한 모든 걱정에 동의합니다. 어떻게 할 수 없습니까? 오해의 소지가 있다고 생각합니다.

무능력 (추상화 또는 서브 클래스)은 실제로 존재하지만 무엇입니까? 그런 의미가 아닙니다. 더 없다 인터페이스 할 수없는 까지로, 내가 말할 수있는가 . 높은 커플 링 도있을 수 있지만 일반적으로 사용되는 방식 때문입니다. 필요하지 않습니다 . 실제로 커플 링 자체는 싱글 톤 패턴과 관련이 없습니다. 명확하게 설명하면 이미 테스트하기가 어렵습니다. 병렬화의 어려움은 언어와 플랫폼에 따라 다르므로 패턴에 문제가 없습니다.

실용적인 예

나는 종종 찬성하거나 싱글 톤에 대해 2가 사용되는 것을 본다. 웹 캐시 (내 경우) 및 로그 서비스 .

로깅은 일부 사람들이 주장 할 것이므로 완벽한 싱글 톤 예제입니다.

  • 요청자는 요청을 로그에 보낼 잘 알려진 객체가 필요합니다. 이것은 글로벌 액세스 지점을 의미합니다.
  • 로깅 서비스는 여러 리스너가 등록 할 수있는 단일 이벤트 소스이므로 하나의 인스턴스 만 있으면됩니다.
  • 응용 프로그램마다 다른 출력 장치에 기록 할 수 있지만 리스너를 등록하는 방식은 항상 동일합니다. 모든 사용자 정의는 리스너를 통해 수행됩니다. 클라이언트는 텍스트의 로그 방법 또는 위치를 모르고 로깅을 요청할 수 있습니다. 따라서 모든 응용 프로그램은 로깅 서비스를 정확히 같은 방식으로 사용합니다.
  • 모든 응용 프로그램은 로깅 서비스 인스턴스를 하나만 사용하여 벗어날 수 있어야합니다.
  • 재사용 가능한 구성 요소를 포함하여 모든 객체가 로깅 요청자가 될 수 있으므로 특정 응용 프로그램에 연결해서는 안됩니다.

다른 사람들은 결국 로그 서비스가 실제로는 하나의 인스턴스가 아니라는 사실을 깨닫고 나면 로그 서비스를 확장하기가 어렵다고 주장합니다.

글쎄, 나는 두 주장이 모두 유효하다고 말한다. 여기서도 문제는 싱글 톤 패턴이 아닙니다. 리팩토링이 실행 가능한 위험이라면 아키텍처 결정과 가중치에 있습니다. 일반적으로 리팩토링이 마지막으로 필요한 수정 조치 인 경우 추가 문제입니다.


답변

싱글 톤 디자인 패턴의 주된 문제는 어플리케이션에 적합한 단위 테스트를 작성하는 것이 매우 어렵다는 것입니다.

이 “관리자”에 종속 된 모든 구성 요소는 해당 단일 인스턴스를 쿼리하여 수행합니다. 이러한 구성 요소에 대한 단위 테스트를 작성하려면이 싱글 톤 인스턴스에 데이터를 주입해야하므로 쉽지 않을 수 있습니다.

반면에 “관리자”가 생성자 매개 변수를 통해 종속 구성 요소에 주입되고 구성 요소가 관리자의 구체적인 유형, 인터페이스 또는 관리자가 구현하는 추상 기본 클래스 만 모르는 경우 테스트는 종속성을 테스트 할 때 관리자의 대체 구현을 제공 할 수 있습니다.

IOC 컨테이너를 사용하여 애플리케이션을 구성하는 구성 요소를 구성하고 인스턴스화하는 경우 하나의 “관리자”인스턴스 만 작성하도록 IOC 컨테이너를 쉽게 구성 할 수 있으므로 글로벌 애플리케이션 캐시를 제어하는 ​​동일한 단일 인스턴스 만 달성 할 수 있습니다. .

그러나 단위 테스트에 신경 쓰지 않는다면 싱글 톤 디자인 패턴이 완벽 할 수 있습니다. (그러나 나는 그것을하지 않을 것입니다)


답변

디자인 컴퓨팅이 좋거나 나쁠 수 있다는 점 에서 싱글 톤은 근본적으로 나쁘지 않습니다. 정확해야합니다 (예상 결과 제공). 코드를 더 명확하거나 효율적으로 만들면 유용하거나 유용하지 않을 수 있습니다.

싱글 톤이 유용한 한 가지 경우는 실제로 고유 한 엔티티를 나타내는 경우입니다. 대부분의 환경에서 데이터베이스는 고유하며 실제로 하나의 데이터베이스 만 있습니다. 해당 데이터베이스에 연결하는 것은 특별한 권한이 필요하거나 여러 연결 유형을 통과하기 때문에 복잡 할 수 있습니다. 단일 연결로 연결을 구성하는 것은 아마도 이런 이유로 많은 의미가 있습니다.

그러나 단일 톤이 실제로 단일 변수이며 전역 변수가 아닌지 확인해야합니다. 이는 하나의 고유 한 데이터베이스가 실제로 4 개의 데이터베이스 (생산, 스테이징, 개발 및 테스트 설비 각각에 대해 하나씩) 인 경우에 중요합니다. Database Singleton은 연결해야 할 인스턴스를 파악하고 해당 데이터베이스의 단일 인스턴스를 잡고 필요한 경우 연결 한 다음 호출자에게 반환합니다.

싱글 톤이 실제로 싱글 톤이 아닌 경우 (대부분의 프로그래머가 화를 낼 때), 느리게 인스턴스화 된 전역이므로 올바른 인스턴스를 주입 할 기회가 없습니다.

잘 설계된 싱글 톤 패턴의 또 다른 유용한 기능은 종종 관찰 할 수 없다는 것입니다. 발신자가 연결을 요청합니다. 이를 제공하는 서비스는 풀링 된 객체를 반환하거나 테스트를 수행하는 경우 모든 호출자에 대해 새 객체를 만들거나 대신 모의 객체를 제공 할 수 있습니다.