싱글톤 패턴

Singleton pattern
싱글톤 패턴을 나타내는 클래스 다이어그램.

소프트웨어 엔지니어링에서 싱글톤 패턴은 클래스인스턴스화를 하나의 "싱글" 인스턴스로 제한하는 소프트웨어 설계 패턴입니다.이 기능은 시스템 전체에서 작업을 조정하기 위해 정확히 하나의 개체가 필요한 경우에 유용합니다.

이 용어는 독신자의 수학적 개념에서 유래했다.

개요

싱글톤 디자인 패턴은 객체 [1]구현, 변경, 테스트 및 재사용을 용이하게 하기 위해 유연하고 재사용 가능한 객체 지향 소프트웨어를 설계하기 위해 반복되는 설계 문제를 해결하는 방법을 설명하는 잘 알려진 23가지 설계 패턴 중 하나입니다.

싱글톤 디자인 패턴은 [2]다음을 가능하게 하여 문제를 해결합니다.

  • 클래스에 인스턴스가 1개만 있는지 확인합니다.
  • 클래스의 단일 인스턴스에 쉽게 액세스
  • 인스턴스화 제어
  • 인스턴스 수 제한
  • 글로벌 변수에 액세스하다

싱글톤 설계 패턴은 이러한 문제를 해결하는 방법을 설명합니다.

  • 클래스생성자를 숨깁니다.
  • 퍼블릭 스태틱 조작을 정의합니다(getInstance()클래스의 유일한 인스턴스를 반환합니다.

본질적으로 싱글톤 패턴은 한 번만 인스턴스화되도록 하는 책임을 지도록 강요합니다.숨김 컨스트럭터: 선언됨private또는protected: 클래스 외부에서 클래스를 인스턴스화할 수 없음을 나타냅니다.퍼블릭 스태틱 조작에는, 클래스명과 조작명을 사용해 액세스 할 수 있습니다.예를 들어, 다음과 같습니다.Singleton.getInstance().

일반적인 용도

  • 추상 공장, 공장 방법, 빌더프로토타입 패턴은 싱글톤을 사용할 수 있습니다.
  • 파사드 객체는 하나의 파사드 객체만 필요하기 때문에 종종 싱글톤입니다.
  • 상태 객체는 종종 싱글톤입니다.
  • 다음과 같은 [3]이유로 싱글톤이 글로벌 변수보다 선호됩니다.
    • 불필요[1]변수로 글로벌네임스페이스(네스트된 네임스페이스가 있는 언어에서는 네임스페이스 포함)를 오염시키지 않습니다.
    • 많은 언어의 글로벌 변수는 항상 리소스를 소비하는 반면, 이러한 변수는 느린 할당과 초기화를 허용합니다.

로깅은 싱글톤의 [4]전형적인 예입니다.

비판

비평가들은 싱글톤이 불필요하게 어플리케이션에 글로벌스테이트를 도입하기 때문에 안티패턴으로 간주하고 있습니다.따라서 싱글톤을 사용하는 추상화에 제한을 가할 수 있습니다.예를 들어 여러 [5][6][7][8]인스턴스의 동시 사용을 막는 등입니다.또, 그 존재는, 글로벌하게 볼 수 있는 액세스로서 자주 공개되기 때문에, 그 존재는, 보이는 모든 코드에 싱글톤에 대한 잠재적인 의존성을 도입하는 것으로, 의존성 분석을 복잡하게 합니다.따라서, 실제로 의존성이 [9]존재하는지 아닌지를 판단하기 위해서, 실장 상세를 분석할 필요가 있습니다.

싱글톤은 싱글톤의 통상적인 태스크에 책임을 질 뿐만 아니라 하나의 태스크만 인스턴스화해야 하기 때문에 싱글톤은 [5]예를 들어 스태틱을 통해 자신의 고유성을 강제하는 "클래식" 싱글톤 정의에 의존합니다.getInstance()방법.

또 다른 단점은 싱글톤이 프로그램[dubious ] 기간 동안 글로벌 상태를 유지하기 때문에 테스트하기 어렵다는[dubious ] 것입니다.특히 유닛 테스트에서는 테스트 대상을 [5]분리하기 위해 느슨하게 결합된 클래스가 필요하기 때문입니다.또한 특정 클래스가 싱글톤과 상호작용할 때 해당 클래스와 싱글톤은 밀접하게[dubious ] 결합되어 싱글톤을[dubious ] [9]테스트하지 않고는 클래스를 자체적으로 테스트할 수 없습니다.

실장

싱글톤 패턴의 실장은, 다음과 같이 실시할 필요가 있습니다.

  • 싱글톤 클래스의 인스턴스가 1개만 존재하는지 확인합니다.
  • 해당 인스턴스에 대한 글로벌 액세스를 제공합니다.

일반적으로 이 작업은 다음과 같이 수행됩니다.

  • 클래스의 모든 컨스트럭터를 비공개로 선언한다.
  • 인스턴스에 대한 참조를 반환하는 정적 메서드를 제공합니다.

인스턴스는 보통 개인 스태틱 변수로 저장됩니다.인스턴스는 변수가 초기화되었을 때 스태틱메서드가 처음 호출되기 전의 어느 시점에서 생성됩니다.

자바

Java에서의 [10]싱글톤 구현:

일반의 학급 동전 {      사적인 정적인 최종 인트 추가_모어_코인 = 10;     사적인 인트 화폐를 만들다;     사적인 정적인 동전 사례 = 신규 동전(); // 싱글톤을 열심히 로드합니다.      사적인 동전() {         // 다른 사용자가 인스턴스화하는 것을 방지하기 위해 비공개     }      일반의 정적인 동전 get Instance(인스턴스() {         돌아가다 사례;     }      일반의 인트 get코인() {         돌아가다 화폐를 만들다;     }      일반의 무효 추가 코인() {         화폐를 만들다 += 추가_모어_코인;     }      일반의 무효 차감코인() {         화폐를 만들다--;     } } 
일반의 학급 싱글턴 {      사적인 정적인 최종 싱글턴 사례 = 신규 싱글턴();      사적인 싱글턴() {}      일반의 정적인 싱글턴 get Instance(인스턴스() {         돌아가다 사례;     } } 

느린 초기화

싱글톤 실장에서는 스태틱메서드가 처음 호출되었을 때 인스턴스가 작성되는 느린 초기화를 사용할 수 있습니다.스태틱 메서드를 여러 스레드에서 동시에 호출할 수 있는 경우 여러 인스턴스가 생성될 수 있는 레이스 조건을 방지하기 위한 조치가 필요할 수 있습니다.다음은 Java로 작성된 이중 체크 잠금과 느린 초기화를 사용한 스레드 세이프 구현입니다.스레드 안전과 함께 느린 초기화를 유지하면서 동기화 오버헤드를 피하기 위해 Java에서는 Initialization-on-demand 홀더 [citation needed]idi를 사용하는 것이 좋습니다.

일반의 학급 싱글턴 {      사적인 정적인 휘발성의 싱글턴 사례 = 무효;      사적인 싱글턴() {}      일반의 정적인 싱글턴 get Instance(인스턴스() {         한다면 (사례 == 무효) {             동기화된(싱글턴.학급) {                 한다면 (사례 == 무효) {                     사례 = 신규 싱글턴();                 }             }         }          돌아가다 사례;     } } 
일반의 최종 학급 Singleton Double Checked 잠금 {  사적인 정적인 Singleton Double Checked 잠금 사례;  사적인 정적인 부울 초기화하다 = 진실의;   사적인 Singleton Double Checked 잠금() {  }   일반의 정적인 Singleton Double Checked 잠금 get Instance(인스턴스() {   한다면 (초기화하다) {    동기화된 (Singleton Double Checked 잠금.학급) {     한다면 (초기화하다) {      사례 = 신규 Singleton Double Checked 잠금();      초기화하다 = 거짓의;     }    }   }   돌아가다 사례;  } } 
일반의 최종 학급 싱글톤 빌퍼그 {  사적인 정적인 학급 싱글턴도우미 {   사적인 정적인 최종 싱글톤 빌퍼그 사례 = 신규 싱글톤 빌퍼그();  }   사적인 싱글톤 빌퍼그() {  }   일반의 정적인 싱글톤 빌퍼그 getIstance() {   돌아가다 싱글턴도우미.사례;  } } 

파이썬

학급 싱글턴:     __개요 = 없음.      방어하다 __new__(클릭, *args):         한다면 클릭.__개요  없음.:             클릭.__개요 = 물건.__new__(클릭, *args)         돌아가다 클릭.__개요 

C++

C++11 현재 스태틱로컬 변수의 초기화는 스레드 세이프이며 첫 번째 [11]호출 후에 이루어집니다.이는 네임스페이스 또는 클래스 범위 정적 변수보다 안전한 방법입니다.

학급 싱글턴 {  일반의:   정적인 싱글턴& GetInstance() {     //싱글턴이 완전히 파괴되지 않는 경우 'new'로 할당합니다.     정적인 싱글턴* 싱글톤 = 신규 싱글턴();     돌아가다 *싱글톤;   }   사적인:   싱글턴() = 체납;    // 추가 인스턴스를 만들거나 이동할 수 없도록 복사/이동 삭제   싱글턴(컨스턴트 싱글턴&) = 삭제하다;   싱글턴& 교환입니다.=(컨스턴트 싱글턴&) = 삭제하다;   싱글턴(싱글턴& &) = 삭제하다;   싱글턴& 교환입니다.=(싱글턴& &) = 삭제하다; }; 

C#

C#에서의 싱글턴 실장:

일반의 밀봉된 학급 싱글턴 {     사적인 정적인 휘발성의 싱글턴? _개요;     사적인 정적인 읽기 전용 물건 _잠금 = 신규 물건();      사적인 싱글턴() { }      일반의 정적인 싱글턴 사례     {         얻다         {             한다면 (_개요 != 무효)             {                 돌아가다 _개요;             }              잠그다 (_잠금)             {                 한다면 (_개요 == 무효)                     _개요 = 신규 싱글턴();             }              돌아가다 _개요;         }     } } 

C#에서는 static 클래스를 사용하여 싱글톤을 만들 수도 있습니다.여기서 클래스 자체는 싱글톤입니다

일반의 정적인 학급 싱글턴 {     일반의 정적인 MyOtherClass 사례 { 얻다; } = 신규 MyOtherClass(); } 

유니티

싱글톤은 클래스가 인스턴스화되기 때문에 Unity를 사용하여 개발할 때 유용한 도구가 될 수 있습니다.이 메서드는 Unity에서 숨겨진 컨스트럭터를 사용하여 개체를 인스턴스화할 수 있으므로 컨스트럭터 숨기기보다 선호됩니다.인스턴스가 덮어쓰기되지 않도록 하려면 인스턴스가 다음 상태인지 확인해야 합니다.nullnull이 아닌 경우GameObject문제가 되는 스크립트가 포함되어 있는 경우는 파기해야 합니다.

다른 컴포넌트가 싱글톤에 의존하는 경우 싱글톤을 정의하는 컴포넌트가 먼저 실행되도록 스크립트 실행 순서를 변경해야 합니다.

학급 싱글턴 : 단일 행동 {     일반의 정적인 싱글턴 사례 { 얻다; 사적인 세트; }      사적인 무효 깨어 있는()     {         한다면 (사례 != 무효 & & 사례 != 이것.)         {             파괴하다(이것..게임 오브젝트);         }         또 다른         {             사례 = 이것.;         }     } } 

싱글톤을 실장하는 것도 문제가 되는 스크립트만 삭제해도 가능합니다.GameObject대신 전화하는 것만으로Destroy(this).

다트

Dart에서의 싱글톤 구현:

학급 싱글턴 {     싱글턴._();     정적인 싱글턴 얻다 사례 => 싱글턴._(); } 

PHP

PHP에서의 싱글톤 구현:

학급 싱글턴 {     사적인 정적인 싱글턴 $140;      사적인 기능. __개요() {}      일반의 정적인 기능. get Instance(인스턴스(): 자신     {         한다면 (!세트(자신::$140)) {             자신::$140 = 신규 자신();         }          돌아가다 자신::$140;     } } 

코틀린

Kotlin object 키워드는 싱글톤클래스를[10][12] 선언합니다.

물건 동전 {     사적인 변화하다 화폐를 만들다: 내부 = 0      재밌어요 get코인():내부 {         돌아가다 화폐를 만들다     }      재밌어요 추가 코인() {         화폐를 만들다 += 10     }      재밌어요 차감코인() {         화폐를 만들다--     } } 

파스칼

Pascal에서 싱글톤스레드 세이프 구현:

구성 단위 싱글톤 패턴;  인터페이스  유형   테스트 = 학급 밀봉된   엄격한. 사적인     FCreation시간을: TDate 시간;   일반의     컨스트럭터 만들다;     소유물 창조.시간을: TDate 시간 읽어주세요 FCreation시간을;   끝.;  기능. GetInstance: 테스트;  실행  사용하다   시스템 유틸   , SyncObjs   ;  변화하다   FCritical 섹션: TCritical 섹션;   기능: 테스트;  기능. GetInstance: 테스트; 시작한다.   FCritical 섹션.얻다;   해라     한다면 것은 아니다. 맡겨진(기능) 그리고나서       기능 := 테스트.만들다;      결과 := 기능;   마침내.     FCritical 섹션.풀어주다;   끝.; 끝.;  컨스트럭터 테스트.만들다; 시작한다.   상속된 만들다;   FCreation시간을 := 지금이다; 끝.;  초기화   FCritical 섹션 := TCritical 섹션.만들다;  최종화   프리앤닐(FCritical 섹션);  끝.. 

사용방법:

절차. TForm3.btnCreateInstance클릭(송신자: 토브젝트); 변화하다   i: 정수; 시작한다.   위해서 i := 0 로. 5 하다     Show Message(메시지 표시)(Date Time To Str(GetInstance.창조.시간을)); 끝.; 

가세요

Go에서의 싱글턴 실장.

패키지 주된  유형 싱글턴 구조 {}  변화하다 사례 *싱글턴  기능하다 GetInstance() *싱글턴 {  한다면 사례 != 제로 {   돌아가다 사례  }  사례 = 신규(싱글턴)  돌아가다 사례 } 

「 」를 참조해 주세요.

레퍼런스

  1. ^ a b Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. pp. 127ff. ISBN 0-201-63361-2.{{cite book}}: CS1 maint: 여러 이름: 작성자 목록(링크)
  2. ^ "The Singleton design pattern - Problem, Solution, and Applicability". w3sDesign.com. Retrieved 2017-08-16.
  3. ^ Soni, Devin (31 July 2019). "What Is a Singleton?". BetterProgramming. Retrieved 28 August 2021.
  4. ^ Rainsberger, J.B. (1 July 2001). "Use your singletons wisely". IBM. Archived from the original on 24 February 2021. Retrieved 28 August 2021.
  5. ^ a b c Button, Brian (25 May 2004). "Why Singletons are Evil". Being Scott Densmore. Microsoft. Archived from the original on 15 July 2021. Retrieved 28 August 2021.
  6. ^ 스티브 예지싱글톤은 멍청하다고 여겨져 2004년 9월
  7. ^ Hebery, Mishko, "글로벌 스테이트와 싱글톤", Clean Code Talks, 2008년 11월 21일.
  8. ^ Contieri, Maximiliano (13 July 2020). "Singleton Pattern: The Root of All Evil". Hacker Noon. Retrieved 28 August 2021.
  9. ^ a b "Why Singletons Are Controversial". Google Code Archive. Archived from the original on 6 May 2021. Retrieved 28 August 2021.
  10. ^ a b "Are you an Android Developer and not using Singleton Class yet?". 16 April 2020.
  11. ^ "Storage class specifiers: Static local variables". Cppreference. Retrieved 28 August 2021.
  12. ^ "Object declarations". Retrieved 2020-05-19.

외부 링크