IT

싱글 톤 : 어떻게 사용해야합니까

lottoking 2020. 3. 20. 08:29
반응형

싱글 톤 : 어떻게 사용해야합니까


편집 : 다른 질문에서 싱글 톤에 대한 많은 질문 / 답변으로 연결되는 답변을 제공했습니다. 싱글 톤에 대한 자세한 정보는 다음과 같습니다.

그래서 Singletons 스레드를 읽었습니다 : 좋은 디자인 또는 목발?
그리고 논쟁은 여전히 ​​분노합니다.

나는 싱글 톤을 디자인 패턴으로보고있다.

싱글 톤의 문제는 패턴이 아니라 사용자 (죄송합니다)입니다. 모두와 그들의 아버지는 그들이 정확하게 하나를 구현할 수 있다고 생각합니다 (그리고 내가 한 많은 인터뷰에서 대부분의 사람들은 할 수 없습니다). 또한 모두가 올바른 싱글 톤을 구현할 수 있다고 생각하기 때문에 패턴을 남용하여 적절하지 않은 상황에서 사용합니다 (전역 변수를 싱글 톤으로 대체!).

따라서 대답해야 할 주요 질문은 다음과 같습니다.

  • 언제 싱글 톤을 사용해야합니까
  • 싱글 톤을 올바르게 구현하는 방법

이 기사에 대한 희망은 싱글 톤을 올바르게 사용하는시기와 방법에 대한 권위있는 출처 (여러 사이트를 검색하고 검색하지 않고)를 한 곳에 모을 수 있기를 희망합니다. 또한 사용하지 않는 이유와 좋은 구현의 단점을 설명하는 안티 사용 및 일반적인 나쁜 구현 목록이 적합합니다.


공을 굴리십시오.
나는 손을 잡고 이것이 내가 사용하지만 문제가 있다고 말합니다.
나는 그의 책 "Effective C ++"에서 주제를 다루는 "Scott Myers"를 좋아한다

싱글 톤을 사용하는 좋은 상황 :

  • 로깅 프레임 워크
  • 스레드 재활용 풀
/*
 * C++ Singleton
 * Limitation: Single Threaded Design
 * See: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
 *      For problems associated with locking in multi threaded applications
 *
 * Limitation:
 * If you use this Singleton (A) within a destructor of another Singleton (B)
 * This Singleton (A) must be fully constructed before the constructor of (B)
 * is called.
 */
class MySingleton
{
    private:
        // Private Constructor
        MySingleton();
        // Stop the compiler generating methods of copy the object
        MySingleton(MySingleton const& copy);            // Not Implemented
        MySingleton& operator=(MySingleton const& copy); // Not Implemented

    public:
        static MySingleton& getInstance()
        {
            // The only instance
            // Guaranteed to be lazy initialized
            // Guaranteed that it will be destroyed correctly
            static MySingleton instance;
            return instance;
        }
};

확인. 비판과 다른 구현을 함께합시다.
:-)


모두 잘못되었습니다. 질문을 읽으십시오. 대답:

다음과 같은 경우 싱글 톤을 사용하십시오.

  • 시스템에 하나의 유형의 객체가 하나만 있어야합니다.

다음과 같은 경우 싱글 톤을 사용하지 마십시오.

  • 메모리를 절약하고 싶습니다
  • 새로운 것을 시도하고 싶다
  • 당신은 당신이 알고 얼마나 과시하고 싶어
  • 다른 모든 사람들이 그렇게하기 때문에 ( wikipedia의 화물 컬트 프로그래머 참조 )
  • 사용자 인터페이스 위젯에서
  • 캐시 여야합니다
  • 문자열에서
  • 세션에서
  • 하루 종일 갈 수있어

최고의 싱글 톤을 만드는 방법 :

  • 작을수록 좋습니다. 나는 미니멀리스트입니다
  • 나사산이 안전한지 확인하십시오
  • 절대 null이 아닌지 확인하십시오
  • 한 번만 작성하십시오
  • 게으른 또는 시스템 초기화? 요구 사항까지
  • 때때로 OS 또는 JVM이 싱글 톤을 생성합니다 (예 : Java에서 모든 클래스 정의는 싱글 톤임)
  • 소멸자를 제공하거나 어떻게 든 자원을 처분하는 방법을 알아냅니다.
  • 적은 메모리 사용

싱글 톤은 하나의 클래스에서 두 가지 나쁜 특성을 결합하는 기능을 제공합니다. 그것은 거의 모든면에서 잘못되었습니다.

싱글 톤이 제공합니다 :

  1. 객체에 대한 글로벌 액세스
  2. 이 유형의 개체를 둘 이상 만들 수 없다는 보장

첫 번째는 간단합니다. 세계는 일반적으로 나쁘다. 실제로 필요한 경우가 아니면 전역 적으로 액세스 가능한 객체를 만들면 안됩니다 .

두 번째는 말이되는 것처럼 들리 겠지만 생각해 보자. 기존 객체를 참조하는 대신 마지막으로 ** 실수로 * 새로운 객체를 만든 시간은 언제입니까? C ++로 태그가 지정되었으므로 해당 언어의 예제를 사용하십시오. 실수로 글을 쓰십니까

std::ostream os;
os << "hello world\n";

쓰려고 할 때

std::cout << "hello world\n";

당연히 아니지. 이런 종류의 오류는 발생하지 않기 때문에이 오류에 대한 보호가 필요하지 않습니다. 만일 그렇다면, 집에 가서 12-20 시간 동안 자고 기분이 나아지기를 바랍니다.

객체가 하나만 필요한 경우 인스턴스를 하나만 만들면됩니다. 하나의 객체가 전역 적으로 액세스 가능해야하는 경우 전역으로 만드십시오. 그렇다고 다른 인스턴스를 만드는 것이 불가능하다는 의미는 아닙니다.

"단일 인스턴스 만 가능"제약 조건은 버그 가능성으로부터 실제로 우리를 보호하지 않습니다. 그러나 않습니다 리팩토링 열심히 우리의 코드를 확인하고 유지합니다. 우리는 종종 하나 이상의 인스턴스가 필요하다는 것을 나중에 알기 때문에 . 우리는 어떻게 우리가 하나 이상의 데이터베이스가 않습니다 , 우리는 여러 로거를 하나 이상 구성 개체를 원하는가했다. 우리의 단위 테스트는 일반적인 테스트를 위해 매 테스트마다 이러한 개체를 생성하고 다시 만들 수 있기를 원할 수 있습니다.

싱글은 경우에만 사용해야합니다 그래서, 우리는 필요 모두에게 그것을 제공하는 특성을 우리가 경우에 필요한 글로벌 액세스 (전역은 일반적으로 낙심하고 있기 때문에, 희소 인) 우리가 필요로 하는 사람을 방지하기 위해 (A)의 하나 개 이상의 인스턴스를 생성 클래스 (디자인 문제처럼 들립니다). 내가 볼 수있는 유일한 이유는 두 개의 인스턴스를 만들면 응용 프로그램 상태가 손상 될 수 있기 때문입니다. 아마 클래스에 여러 정적 멤버 또는 유사한 어리 석음이 포함되어 있기 때문일 수 있습니다. 어떤 경우에 그 대답은 그 클래스를 고치는 것입니다. 유일한 인스턴스에 의존해서는 안됩니다.

객체에 대한 전역 액세스가 필요한 경우와 같이 전역으로 만듭니다 std::cout. 그러나 생성 할 수있는 인스턴스 수를 제한하지 마십시오.

절대적으로 클래스의 인스턴스 수를 하나만으로 제한해야하며 두 번째 인스턴스 생성을 안전하게 처리 할 수있는 방법이 없다면 시행하십시오. 그러나 전 세계적으로 접근 가능하도록 만들지 마십시오.

두 가지 특성이 모두 필요하다면 1) 싱글 톤으로 만들고 2) 그런 경우를 상상하기가 어렵 기 때문에 필요한 것을 알려주십시오.


싱글 톤의 문제점은 구현이 아닙니다. 그것들은 두 가지 다른 개념을 혼동한다는 것입니다.

1) 싱글 톤은 객체에 대한 전역 액세스 메커니즘을 제공합니다. 비록 잘 정의 된 초기화 순서가없는 언어에서는 그것들이 스레드로부터 안전하거나 조금 더 안정적 일 수 있지만,이 사용법은 여전히 ​​전역 변수와 도덕적으로 동일합니다. 이 변수는 어색한 구문 (g_foo 대신 foo :: get_instance ())으로 작성된 전역 변수이지만 동일한 목적 (전체 프로그램에서 액세스 가능한 단일 객체)을 제공하며 동일한 단점을 가지고 있습니다.

2) 싱글 톤은 클래스의 다중 인스턴스화를 방지합니다. 이런 종류의 기능을 클래스로 구워야하는 경우는 거의 없습니다. 일반적으로 상황이 훨씬 더 중요합니다. 일대일로 간주되는 많은 것들이 실제로는 일대일 일뿐입니다. IMO보다 적합한 솔루션은 인스턴스가 하나 이상 필요하다는 사실을 알 때까지 인스턴스를 하나만 만드는 것입니다.


패턴이있는 한 가지 : 일반화하지 마십시오 . 그들은 유용하고 실패 할 때 모든 경우를 가지고 있습니다.

코드 테스트 해야 할 때 싱글 톤이 불쾌 할 수 있습니다 . 일반적으로 클래스의 인스턴스 하나에 붙어 있으며 생성자에서 문을 열거 나 상태를 재설정하는 방법 등을 선택할 수 있습니다.

다른 문제는 실제로 싱글 톤 은 변장에 있는 전역 변수지나지 않는다는 것 입니다. 프로그램에 비해 너무 많은 전역 공유 상태가 있으면 상황이 거꾸로 돌아가는 경향이 있습니다. 모두 알고 있습니다.

종속성 추적이 더 어려워 질 수 있습니다 . 모든 것이 싱글 톤에 의존 할 때, 변경하기가 더 어렵고, 둘로 나뉘 기 어렵습니다. 이것은 또한 유연성을 방해합니다. 이 문제를 완화하기 위해 일부 Dependency Injection 프레임 워크를 조사하십시오 .


싱글 톤은 기본적으로 복잡한 전역 변수를 갖는 것이 어렵거나 불가능한 언어로 복잡한 전역 상태를 가질 수 있습니다.

Java는 특히 단일 변수를 전역 변수의 대체물로 사용합니다. 모든 것이 클래스 내에 포함되어야하기 때문입니다. 전역 변수에 가장 근접한 것은 공용 정적 변수이며 전역 변수처럼 사용할 수 있습니다import static

C ++에는 전역 변수가 있지만 전역 클래스 변수의 생성자가 호출되는 순서는 정의되어 있지 않습니다. 따라서 싱글 톤을 사용하면 변수가 처음 필요할 때까지 전역 변수 작성을 연기 할 수 있습니다.

파이썬과 루비와 같은 언어는 단일 톤을 거의 사용하지 않습니다. 모듈 내에서 전역 변수를 대신 사용할 수 있기 때문입니다.

그렇다면 싱글 톤을 사용하는 것이 언제 / 좋은가? 전역 변수를 사용하는 것이 좋거나 나쁠 때와 거의 같습니다.


Alexandrescu의 최신 C ++ 디자인 에는 스레드 안전하고 상속 가능한 일반 싱글 톤이 있습니다.

내 2p-worth의 경우 싱글 톤의 수명을 정의하는 것이 중요하다고 생각합니다 (절대로 사용해야 할 때). 나는 보통 정적 get()함수가 아무것도 인스턴스화 하지 못하게 하고 기본 응용 프로그램의 일부 전용 섹션에 설정 및 파괴를 남겨 둡니다. 이는 싱글 톤 간의 종속성을 강조하는 데 도움이되지만 위에서 강조한 것처럼 가능한 경우 피하는 것이 가장 좋습니다.


  • 싱글 톤을 올바르게 구현하는 방법

한 번도 언급 한 적이없는 한 가지 문제가 있습니다. 이전 작업에서 발생한 문제입니다. 우리는 DLL간에 공유되는 C ++ 싱글 톤을 가지고 있었고 클래스의 단일 인스턴스가 작동하지 않도록하는 일반적인 메커니즘을 가지고 있습니다. 문제는 각 DLL이 EXE와 함께 자체 정적 변수 세트를 얻는다는 것입니다. get_instance 함수가 인라인 또는 정적 라이브러리의 일부인 경우, 각 DLL은 "단일"의 자체 사본으로 구성됩니다.

해결 방법은 싱글 톤 코드가 하나의 DLL 또는 EXE에만 정의되어 있는지 확인하거나 해당 속성을 가진 싱글 톤 관리자를 만들어 인스턴스를 소포하는 것입니다.


첫 번째 예제는 스레드로부터 안전하지 않습니다. 두 개의 스레드가 동시에 getInstance를 호출하면 해당 정적은 PITA가됩니다. 어떤 형태의 뮤텍스가 도움이 될 것입니다.


다른 사람들이 지적했듯이 싱글 톤의 주요 단점은 확장 할 수 없으며 테스트 목적으로 둘 이상의 인스턴스를 인스턴스화 할 수있는 힘을 잃는 것입니다.

싱글 톤의 유용한 측면 :

  1. 게 으르거나 선행 인스턴스화
  2. 설정 및 / 또는 상태가 필요한 객체에 편리

그러나 이러한 이점을 얻기 위해 싱글 톤을 사용할 필요는 없습니다. 작업을 수행하는 일반 객체를 작성한 다음 사람들이 공장 (별도의 객체)을 통해 액세스하도록 할 수 있습니다. 공장은 필요할 경우 인스턴스화 및 재사용 등에 대해 걱정할 수 있습니다. 또한 구체적인 클래스가 아닌 인터페이스로 프로그래밍하면 팩토리에서 전략을 사용할 수 있습니다. 즉, 인터페이스의 다양한 구현을 켜고 끌 수 있습니다.

마지막으로, 공장은 Spring과 같은 의존성 주입 기술에 적합합니다.


싱글 톤은 초기화하고 객체화 할 때 많은 코드가 실행될 때 편리합니다. 예를 들어, 영속 객체를 설정할 때 iBatis를 사용하는 경우 코드에 도달하기 전에 모든 구성을 읽고 맵을 구문 분석하고 모든 것이 올바른지 확인해야합니다.

매번이 작업을 수행하면 성능이 크게 저하됩니다. 싱글 톤으로 사용하면 한 번 적중 한 다음 모든 후속 통화에서 수행 할 필요가 없습니다.


싱글 톤의 진정한 몰락은 상속을 깰 수 있다는 것입니다. Singleton이 참조되는 코드에 액세스 할 수 없으면 확장 된 기능을 제공하기 위해 새 클래스를 파생시킬 수 없습니다. 따라서 Singleton은 코드를 단단히 결합하여 (전략 패턴 ... 일명 종속성 주입으로 수정 가능) 코드 섹션을 수정 (공유 라이브러리)에서 종료하지 못하게합니다.

따라서 로거 또는 스레드 풀의 예도 유효하지 않으므로 전략으로 대체해야합니다.


대부분의 사람들은 전역 변수 사용에 대해 기분이 좋을 때 싱글 톤을 사용합니다. 합법적 인 용도가 있지만 사람들이 사용하는 대부분의 경우 인스턴스가 하나만 존재할 수 있다는 사실은 전 세계적으로 액세스 할 수 있다는 사실과 비교할 때 사소한 사실입니다.


Because a singleton only allows one instance to be created it effectively controls instance replication. for example you'd not need multiple instances of a lookup - a morse lookup map for example, thus wrapping it in a singleton class is apt. And just because you have a single instance of the class does not mean you are also limited on the number of references to that instance. You can queue calls(to avoid threading issues) to the instance and effect changes necessary. Yes, the general form of a singleton is a globally public one, you can certainly modify the design to create a more access restricted singleton. I haven't tired this before but I sure know it is possible. And to all those who commented saying the singleton pattern is utterly evil you should know this: yes it is evil if you do not use it properly or within it confines of effective functionality and predictable behavior: do not GENERALIZE.


그러나 Singleton과 같은 것이 필요할 때 종종 Schwarz Counter사용하여 인스턴스화합니다.


저는 싱글 톤을 인터뷰 테스트로 사용합니다.

개발자에게 일부 디자인 패턴의 이름을 물어볼 때 이름을 지정할 수있는 모든 것이 Singleton이면 고용되지 않습니다.


아래는 소멸자 자체에서 메모리를 할당 해제하여 스레드 안전 싱글 톤 패턴을 구현하는 더 좋은 방법입니다. 그러나 프로그램이 종료되면 싱글 톤 인스턴스가 자동으로 파괴되므로 소멸자는 선택 사항이어야한다고 생각합니다.

#include<iostream>
#include<mutex>

using namespace std;
std::mutex mtx;

class MySingleton{
private:
    static MySingleton * singletonInstance;
    MySingleton();
    ~MySingleton();
public:
    static MySingleton* GetInstance();
    MySingleton(const MySingleton&) = delete;
    const MySingleton& operator=(const MySingleton&) = delete;
    MySingleton(MySingleton&& other) noexcept = delete;
    MySingleton& operator=(MySingleton&& other) noexcept = delete;
};

MySingleton* MySingleton::singletonInstance = nullptr;
MySingleton::MySingleton(){ };
MySingleton::~MySingleton(){
    delete singletonInstance;
};

MySingleton* MySingleton::GetInstance(){
    if (singletonInstance == NULL){
        std::lock_guard<std::mutex> lock(mtx);
        if (singletonInstance == NULL)
            singletonInstance = new MySingleton();
    }
    return singletonInstance;
}

싱글 톤 클래스를 사용해야하는 상황에 대해-프로그램 실행 전체에서 인스턴스 상태를 유지하려는 경우 파일의 한 인스턴스 만 필요한 애플리케이션의 실행 로그에 기록하는 경우 사용되는 등. 아무도 내 위 코드에서 최적화를 제안 할 수 있다면 감사 할 것입니다.


사용 방지 :

과도한 싱글 톤 사용의 한 가지 주요 문제점은 패턴이 대체 구현의 쉬운 확장 및 교체를 방지한다는 것입니다. 클래스 이름은 싱글 톤이 사용되는 곳마다 하드 코딩됩니다.


이것이 C # 에서 가장 강력한 버전 이라고 생각합니다 .

using System;
using System.Collections;
using System.Threading;

namespace DoFactory.GangOfFour.Singleton.RealWorld
{

  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Same instance?
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 server requests
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // "Singleton"

  class LoadBalancer
  {
    private static LoadBalancer instance;
    private ArrayList servers = new ArrayList();

    private Random random = new Random();

    // Lock synchronization object
    private static object syncLock = new object();

    // Constructor (protected)
    protected LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      // Support multithreaded applications through
      // 'Double checked locking' pattern which (once
      // the instance exists) avoids locking each
      // time the method is invoked
      if (instance == null)
      {
        lock (syncLock)
        {
          if (instance == null)
          {
            instance = new LoadBalancer();
          }
        }
      }

      return instance;
    }

    // Simple, but effective random load balancer

    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

.NET 최적화 버전 은 다음과 같습니다 .

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Singleton.NETOptimized
{

  // MainApp test application

  class MainApp
  {

    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Confirm these are the same instance
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 requests for a server
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // Singleton

  sealed class LoadBalancer
  {
    // Static members are lazily initialized.
    // .NET guarantees thread safety for static initialization
    private static readonly LoadBalancer instance =
      new LoadBalancer();

    private ArrayList servers = new ArrayList();
    private Random random = new Random();

    // Note: constructor is private.
    private LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      return instance;
    }

    // Simple, but effective load balancer
    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

이 패턴은 dotfactory.com 에서 찾을 수 있습니다 .


Meyers 싱글 톤 패턴은 대부분의 시간 동안 충분히 잘 작동하며 경우에 따라 더 나은 것을 찾기 위해 돈을 지불 할 필요는 없습니다. 생성자가 절대로 던지지 않고 싱글 톤 사이에 종속성이없는 한.

싱글 톤은 모든 GAO가 싱글 톤 인 것은 아니지만 전역 적으로 액세스 가능한 객체 (지금부터 GAO )에 대한 구현입니다 .

로거 자체는 싱글 톤이 아니어야하지만, 로그 방법은 로그 메시지가 생성되는 위치 또는 방법에서 로그 메시지가 생성되는 위치를 분리하기 위해 이상적으로 전역 적으로 액세스 할 수 있어야합니다.

게으른 로딩 / 게으른 평가는 다른 개념이며 싱글 톤도 일반적으로 구현합니다. 그것은 자체적으로 많은 문제, 특히 스레드 안전성과 예외가 발생했을 때 문제가 발생했을 때 좋은 아이디어처럼 보이는 것이 결국에는 그리 좋지 않은 것으로 나타났습니다. (문자열의 COW 구현과 약간 비슷 함).

이를 염두에두고 GOA를 다음과 같이 초기화 할 수 있습니다.

namespace {

T1 * pt1 = NULL;
T2 * pt2 = NULL;
T3 * pt3 = NULL;
T4 * pt4 = NULL;

}

int main( int argc, char* argv[])
{
   T1 t1(args1);
   T2 t2(args2);
   T3 t3(args3);
   T4 t4(args4);

   pt1 = &t1;
   pt2 = &t2;
   pt3 = &t3;
   pt4 = &t4;

   dostuff();

}

T1& getT1()
{
   return *pt1;
}

T2& getT2()
{
   return *pt2;
}

T3& getT3()
{
  return *pt3;
}

T4& getT4()
{
  return *pt4;
}

그렇게 정밀하게 수행 할 필요는 없으며 객체를 포함하는로드 된 라이브러리에서 명확하게 수명을 관리하는 다른 메커니즘을 원할 것입니다. (라이브러리를로드 할 때 얻을 수있는 객체에 넣으십시오).

싱글 톤을 사용하는 경우는? dlopen으로로드 된 라이브러리를 나타내는 싱글 톤 테이블-로거가 가입 할 수 있고 메시지를 보낼 수있는 메시지 핸들러입니다. 신호 처리기에 특별히 필요합니다.


나는 왜 싱글 톤이 세계적이어야 하는지를 알지 못한다.

클래스 내부의 데이터베이스를 개인 상수 정적 변수로 숨기고 데이터베이스를 사용자에게 노출시키지 않고 데이터베이스를 활용하는 클래스 함수를 만드는 단일 톤을 생성하려고했습니다.

이 기능이 왜 나쁜지 모르겠습니다.


많은 메모리를 캡슐화하는 클래스가있을 때 유용합니다. 예를 들어 최근에 작업 한 게임에서 매우 큰 연속 메모리 컬렉션을 포함하는 영향 맵 클래스가 있습니다. 시작시 할당 된 모든 것을 종료하고 종료시 모두 해제하기를 원하며 사본 하나만 원합니다. 또한 여러 곳에서 액세스해야합니다. 이 경우 싱글 톤 패턴이 매우 유용하다는 것을 알았습니다.

다른 솔루션이 있다고 확신하지만이 솔루션은 매우 유용하고 구현하기 쉽습니다.


당신이 싱글 톤을 만든 사람이고 그것을 사용하는 사람이라면, 그것을 싱글 톤으로 만들지 마십시오 (단일 톤을 만들지 않고 객체의 특이성을 제어 할 수 있기 때문에 의미가 없습니다). 라이브러리를 사용하여 사용자에게 단 하나의 객체 만 제공하려고합니다 (이 경우 싱글 톤을 만든 사람이지만 사용자는 아닙니다).

싱글 톤은 객체이므로 객체로 사용합니다. 많은 사람들이 단일 메서드를 반환하는 메서드를 호출하여 직접 싱글 톤에 액세스하지만 코드에서 객체가 싱글 톤임을 알기 때문에 해 롭습니다. 나는 싱글 톤을 객체로 사용하는 것을 선호합니다. 생성자를 통해 일반 객체로 사용합니다. 그러면 코드에서 이러한 객체가 싱글 톤인지 아닌지 알지 못하고 종속성을 더 명확하게 만들고 리팩토링에 약간 도움이됩니다 ...


데스크톱 응용 프로그램 (우리는 공룡만이 더 이상 이것을 작성합니다!)은 상대적으로 변경되지 않는 전역 응용 프로그램 설정 (사용자 언어, 파일 도움말 경로, 사용자 기본 설정 등)을 얻는 데 필수적입니다. 그렇지 않으면 모든 클래스와 모든 대화 상자에 전파해야합니다. .

편집-물론 이것들은 읽기 전용이어야합니다!


다른 구현

class Singleton
{
public:
    static Singleton& Instance()
    {
        // lazy initialize
        if (instance_ == NULL) instance_ = new Singleton();

        return *instance_;
    }

private:
    Singleton() {};

    static Singleton *instance_;
};

참고 URL : https://stackoverflow.com/questions/86582/singleton-how-should-it-be-eded

반응형