문제

편집하다:다른 질문에서 나는 싱글톤에 관한 많은 질문/답변에 대한 링크가 있는 답변을 제공했습니다. 싱글톤에 대한 자세한 내용은 여기를 참조하세요.

그래서 스레드를 읽었습니다. 싱글톤:좋은 디자인인가 목발인가?
그리고 그 논쟁은 여전히 ​​​​격렬합니다.

나는 싱글톤을 디자인 패턴(좋든 나쁘든)으로 봅니다.

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

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

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

이 기사에 대한 나의 희망은 싱글톤을 올바르게 사용하는 시기와 방법에 대한 권위 있는 소스를 (구글링하고 여러 사이트를 검색하는 대신) 한 곳에서 함께 수집할 수 있다는 것입니다.또한 작동하지 않는 이유와 좋은 구현의 약점을 설명하는 사용 방지 및 일반적인 잘못된 구현 목록도 적절할 것입니다.


이제 공을 굴려보세요.
나는 손을 들고 이것이 내가 사용하는 것이지만 아마도 문제가 있을 것이라고 말할 것입니다.
나는 "Scott Myers"가 그의 책 "Effective C++"에서 주제를 다루는 것을 좋아합니다.

싱글톤을 사용하기에 좋은 상황(많지는 않음):

  • 로깅 프레임워크
  • 스레드 재활용 풀
/*
 * 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;
        }
};

좋아요.몇 가지 비판과 기타 구현을 함께 살펴보겠습니다.
:-)

도움이 되었습니까?

해결책

여러분 모두 틀렸습니다.질문을 읽어보세요.답변:

다음과 같은 경우 싱글톤을 사용하세요.

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

다음과 같은 경우 싱글톤을 사용하지 마세요.

  • 메모리를 절약하고 싶나요?
  • 새로운 것을 시도하고 싶나요?
  • 당신이 얼마나 알고 있는지 과시하고 싶습니까?
  • 남들 다 하고 있으니까 (참고 카고 컬트 프로그래머 위키피디아에서)
  • 사용자 인터페이스 위젯에서
  • 캐시로 추정됩니다
  • 문자열에서
  • 세션 중
  • 하루 종일 갈 수 있어요

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

  • 작을수록 좋습니다.나는 미니멀리스트이다
  • 스레드로부터 안전한지 확인하세요.
  • null이 아닌지 확인하세요.
  • 한 번만 생성되었는지 확인하세요.
  • 게으른 또는 시스템 초기화?귀하의 요구 사항까지
  • 때로는 OS나 JVM이 싱글톤을 생성하는 경우도 있습니다(예:Java에서는 모든 클래스 정의가 싱글톤입니다)
  • 소멸자를 제공하거나 어떻게든 리소스를 처리하는 방법을 알아냅니다.
  • 적은 메모리 사용

다른 팁

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

싱글톤은 다음을 제공합니다.

  1. 객체에 대한 전역 액세스
  2. 이 유형의 개체가 하나만 있다는 보장 언제든지 생성될 수 있습니다

첫 번째는 간단합니다.전역 변수는 일반적으로 나쁩니다.객체를 전역적으로 액세스할 수 있도록 설정해서는 안 됩니다. 정말 필요해.

두 번째는 말이 되는 것처럼 들릴 수도 있지만, 생각해 봅시다.마지막으로 **실수로* 기존 개체를 참조하는 대신 새 개체를 만든 때는 언제입니까?이는 C++ 태그가 지정되어 있으므로 해당 언어의 예를 사용하겠습니다.실수로 글을 자주 쓰시나요?

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

글을 쓰려고 했을 때

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

당연히 아니지.그런 종류의 오류는 발생하지 않기 때문에 이 오류로부터 보호할 필요가 없습니다.만약 그렇다면, 올바른 반응은 집에 가서 12~20시간 동안 자고 기분이 나아지길 바라는 것입니다.

객체가 하나만 필요한 경우 인스턴스를 하나만 생성하면 됩니다.하나의 개체에 전역적으로 액세스할 수 있어야 하는 경우 해당 개체를 전역 개체로 만듭니다.그러나 이것이 다른 인스턴스를 생성하는 것이 불가능해야 한다는 의미는 아닙니다.

"단 하나의 인스턴스만 가능"이라는 제약 조건은 실제로 발생할 수 있는 버그로부터 우리를 보호하지 않습니다.하지만 그것은 하다 코드를 리팩토링하고 유지하기가 매우 어렵게 만듭니다.왜냐면 우리는 꽤 자주 알아내거든요 나중에 하나 이상의 인스턴스가 필요했습니다.우리 하다 데이터베이스가 두 개 이상이므로 하다 둘 이상의 구성 개체가 있으므로 여러 로거가 필요합니다.우리의 단위 테스트는 일반적인 예를 들어 테스트할 때마다 이러한 객체를 생성하고 다시 생성할 수 있기를 원할 수 있습니다.

따라서 싱글톤은 다음과 같은 경우에만 사용해야 합니다. 둘 다 그것이 제공하는 특성:만약 우리가 필요 전역 액세스(전역 액세스는 일반적으로 권장되지 않으므로 드물다) 그리고 우리 필요 누구든지 못하게 하려고 항상 클래스의 인스턴스를 두 개 이상 생성합니다(제 생각에는 디자인 문제처럼 들립니다).내가 볼 수 있는 유일한 이유는 두 개의 인스턴스를 생성하면 애플리케이션 상태가 손상될 수 있다는 것입니다. 아마도 클래스에 다수의 정적 멤버 또는 유사한 어리석음이 포함되어 있기 때문일 것입니다.이 경우 분명한 대답은 해당 클래스를 수정하는 것입니다.유일한 인스턴스가 되는 것에 의존해서는 안 됩니다.

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

클래스의 인스턴스 수를 하나로 제한해야 하는데 두 번째 인스턴스 생성을 안전하게 처리할 수 있는 방법이 없다면 이를 적용하세요.하지만 전 세계적으로도 액세스할 수 있도록 만들지 마세요.

두 가지 특성이 모두 필요하다면 1) 싱글톤으로 만들고 2) 그 특성이 무엇인지 알려주십시오. 그런 경우는 상상하기 어렵기 때문입니다.

싱글톤의 문제는 구현이 아닙니다.그것은 두 가지 다른 개념을 융합한다는 것인데, 어느 쪽도 분명히 바람직하지 않습니다.

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

2) 싱글톤은 클래스의 다중 인스턴스화를 방지합니다.IME에서는 이런 종류의 기능이 클래스에 포함되어야 하는 경우가 거의 없습니다.일반적으로 훨씬 더 상황에 맞는 것입니다.유일무이한 것으로 간주되는 많은 것들이 실제로는 단지 우연일 뿐인 것입니다.IMO에서 더 적절한 솔루션은 인스턴스가 두 개 이상 필요하다는 사실을 깨달을 때까지 인스턴스를 하나만 생성하는 것입니다.

패턴이 있는 한 가지: 일반화하지 마세요.유용한 경우와 실패하는 경우가 모두 있습니다.

싱글톤은 필요할 때 불쾌할 수 있습니다. 시험 코드.일반적으로 클래스의 한 인스턴스에만 갇혀 있으며 생성자에서 문을 열거나 상태를 재설정하는 일부 메서드 등을 선택할 수 있습니다.

또 다른 문제는 싱글톤이 실제로는 전역 변수 변장.프로그램에 전역 공유 상태가 너무 많으면 상황이 되돌아가는 경향이 있습니다. 우리 모두는 그것을 알고 있습니다.

그것은 만들 수 있습니다 종속성 추적 더 열심히.모든 것이 싱글톤에 달려 있으면 변경하거나 두 개로 분할하는 등의 작업이 더 어렵습니다.당신은 일반적으로 그것에 붙어 있습니다.이는 또한 유연성을 방해합니다.일부 조사 의존성 주입 이 문제를 완화하기 위한 프레임워크입니다.

싱글톤을 사용하면 기본적으로 언어에서 복잡한 전역 상태를 가질 수 있으므로 복잡한 전역 변수를 갖기가 어렵거나 불가능해집니다.

특히 Java는 모든 것이 클래스 내에 포함되어야 하기 때문에 전역 변수 대신 싱글톤을 사용합니다.전역 변수에 가장 가까운 것은 공용 정적 변수로, 마치 전역 변수인 것처럼 사용할 수 있습니다. import static

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

Python 및 Ruby와 같은 언어는 모듈 내에서 전역 변수를 대신 사용할 수 있으므로 싱글톤을 거의 사용하지 않습니다.

그러면 언제 싱글톤을 사용하는 것이 좋거나 나쁠까요?전역 변수를 사용하는 것이 좋은/나쁜 경우와 거의 정확히 일치합니다.

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

내 2p 가치의 경우 싱글톤의 수명을 정의하는 것이 중요하다고 생각합니다(절대적으로 사용해야 하는 경우).나는 평소에 정전기를 허용하지 않습니다 get() 함수는 무엇이든 인스턴스화하고 설정 및 삭제를 기본 애플리케이션의 일부 전용 섹션에 맡깁니다.이는 싱글톤 간의 종속성을 강조하는 데 도움이 됩니다. 하지만 위에서 강조한 것처럼 가능하면 싱글톤을 피하는 것이 가장 좋습니다.

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

제가 한 번도 언급한 적이 없는 문제가 하나 있는데, 이전 직장에서 겪었던 문제입니다.DLL 간에 공유되는 C++ 싱글톤이 있었고 클래스의 단일 인스턴스를 보장하는 일반적인 메커니즘이 작동하지 않았습니다.문제는 각 DLL이 EXE와 함께 자체 정적 변수 세트를 갖는다는 것입니다.get_instance 함수가 인라인이거나 정적 라이브러리의 일부인 경우 각 DLL은 자체 "싱글톤" 복사본을 갖게 됩니다.

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

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

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

싱글톤의 유용한 측면:

  1. 게으른 또는 사전 인스턴스화
  2. 설정 및/또는 상태가 필요한 객체에 편리합니다.

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

마지막으로, 팩토리는 Spring 등과 같은 종속성 주입 기술에 적합합니다.

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

매번 이렇게 하면 성능이 크게 저하됩니다.싱글톤에서 이를 사용하면 해당 히트를 한 번만 받은 다음 모든 후속 호출에서는 이를 수행할 필요가 없습니다.

싱글톤의 진정한 몰락은 상속을 깨뜨린다는 것입니다.싱글톤이 참조되는 코드에 액세스할 수 없으면 확장된 기능을 제공하기 위해 새 클래스를 파생시킬 수 없습니다.따라서 싱글톤이 코드를 긴밀하게 결합하게 한다는 사실 외에도(전략 패턴으로 수정 가능...종속성 주입이라고도 함)을 사용하면 개정(공유 라이브러리)에서 코드 섹션을 닫는 것도 방지할 수 있습니다.

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

대부분의 사람들은 전역 변수를 사용하는 것에 대해 기분이 좋아지도록 노력할 때 싱글톤을 사용합니다.합법적인 용도가 있지만 대부분의 경우 사람들이 이를 사용하는 경우 인스턴스가 하나만 있을 수 있다는 사실은 전역적으로 액세스할 수 있다는 사실에 비하면 사소한 사실일 뿐입니다.

싱글톤은 하나의 인스턴스만 생성하도록 허용하므로 인스턴스 복제를 효과적으로 제어합니다.예를 들어 조회의 여러 인스턴스가 필요하지 않습니다. 예를 들어 모스 조회 맵을 사용하면 싱글톤 클래스로 래핑하는 것이 적절합니다.그리고 클래스의 단일 인스턴스가 있다고 해서 해당 인스턴스에 대한 참조 수가 제한된다는 의미는 아닙니다.스레딩 문제를 방지하기 위해 호출을 인스턴스에 대기열에 추가하고 필요한 변경 사항을 적용할 수 있습니다.예, 싱글톤의 일반적인 형태는 전 세계적으로 공개되는 형식입니다. 액세스가 더 제한된 싱글톤을 만들기 위해 디자인을 수정할 수 있습니다.나는 전에 이것을 지치지 않았지만 그것이 가능하다는 것을 확신합니다.그리고 싱글톤 패턴이 완전히 나쁘다고 말하는 모든 사람들은 이것을 알아야 합니다:예, 제대로 사용하지 않거나 효과적인 기능과 예측 가능한 동작이 제한된 경우에는 악한 것입니다.일반화하지 마십시오.

하지만 싱글톤과 같은 것이 필요할 때 나는 종종 슈바르츠 카운터 인스턴스화합니다.

저는 싱글톤을 면접 테스트로 사용합니다.

개발자에게 디자인 패턴의 이름을 지정해 달라고 요청했는데, 이름을 지정할 수 있는 것이 싱글톤뿐이면 채용되지 않습니다.

다음은 소멸자 자체에서 메모리 할당을 해제하여 스레드로부터 안전한 싱글톤 패턴을 구현하는 더 나은 접근 방식입니다.하지만 프로그램이 종료되면 싱글톤 인스턴스가 자동으로 삭제되므로 소멸자는 선택 사항이어야 한다고 생각합니다.

#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 싱글톤 패턴은 대부분의 경우 잘 작동하며 경우에 따라 더 나은 것을 찾는 데 반드시 비용이 들지는 않습니다.생성자가 절대 throw하지 않고 싱글톤 간에 종속성이 없는 한.

싱글톤은 다음을 구현한 것입니다. 전역적으로 접근 가능한 객체 (지금부터 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_;
};
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top