그만큼싱글 톤 패턴완전 유료 회원입니다.GoF'에스패턴 책,하지만 최근에는 개발자 세계에 의해 고아가 된 것 같습니다. 나는 아직도 많은 싱글 톤을 사용한다.공장 수업, 그리고 당신이 멀티 스레딩 문제 (어떤 클래스와 같은)에 대해 조심해야 할 때, 나는 왜 그렇게 끔찍한 지 알지 못한다.
Stack Overflow는 특히 싱글 톤이 악하다고 동의하는 것으로 추측됩니다. 왜?
귀하의 답변을 "사실, 참고 문헌 또는 특정 전문 지식"
브라이언 버튼 (Brian Button)
그들은 일반적으로 글로벌 인스턴스로 사용됩니다, 왜 그렇게 나쁜가요? 인터페이스를 통해 코드를 노출하는 대신 코드에서 응용 프로그램의 종속성을 숨길 수 있기 때문입니다. 세계를 무언가로 만들어서 지나치지 않도록하십시오.코드 냄새.
그들은단일 책임 원칙: 자신의 창조와 수명주기를 통제한다는 사실 덕분입니다.
그들은 본질적으로 코드를 단단히 만듭니다.결합 된. 이로 인해 많은 경우 테스트가 다소 어려워졌습니다.
응용 프로그램의 수명 동안 상태를 유지합니다. 테스트에 대한 또 다른 히트는 테스트를 주문해야하는 상황으로 끝날 수 있기 때문에 단위 테스트에 큰 문제가되지 않습니다. 왜? 왜냐하면 각 단위 테스트는 다른 단위 테스트와 독립적이어야하기 때문입니다.
싱글 톤은 하나의 문제를 해결합니다.
자원 경합.
리소스가 있다면
(1)는 하나의 인스턴스 만 가질 수 있습니다.
(2) 당신은 그 단일 인스턴스를 관리해야합니다.
네가 필요해.하나씩 일어나는 것.
예는 많지 않습니다. 로그 파일은 큰 파일입니다. 단일 로그 파일을 그냥 버리고 싶지는 않습니다. 플러시, 동기화 및 제대로 닫으려고합니다. 이것은 관리해야하는 단일 공유 자원의 예입니다.
싱글 톤이 필요한 경우는 거의 없습니다. 그들이 나쁜 이유는 그들이 기분이 좋다는 것입니다.글로벌그리고 그들은 GoF의 완전히 지불 된 회원입니다.디자인 패턴책.
글로벌이 필요하다고 생각하면 아마도 끔찍한 디자인 실수를 저지르고있을 것입니다.
일부 코딩 snobs 그냥 영광스러운 세계를 내려다 보면서. 많은 사람들이 싫어하는 것과 같은 방식으로goto성명을 사용하는 아이디어를 싫어하는 사람들이있다.글로벌. 몇 명의 개발자가 특별한 길이로 나가는 것을 보았습니다.글로벌왜냐하면 그들은 하나의 실패를 인정하는 것으로 간주했기 때문입니다. 이상하지만 사실.
실제로하나씩 일어나는 것패턴은 개념의 툴킷에서 유용한 부분 인 프로그래밍 기법 일뿐입니다. 때로는 이상적인 솔루션임을 알게 될 수도 있습니다. 하지만 그것을 사용하면 자랑 스러울 수 있습니다.디자인 패턴그냥 사용하기를 거부 한 것처럼 바보입니다.글로벌.
Google의 Misko Hevery는 정확하게이 주제에 대한 흥미로운 기사를 가지고 있습니다 ...
싱글 톤은 병적 인 거짓말 쟁이입니다.는 싱글 톤을 사용하여 종속성 체인을 파악하고 응용 프로그램을 시작하거나 테스트하는 것을 어렵게하는 방법을 보여주는 단위 테스트 예제가 있습니다. 그것은 학대의 상당히 극단적 인 예이지만 그가 만드는 요점은 여전히 유효합니다.
싱글 톤은 전체적인 상태에 불과합니다. 전역 상태를 사용하면 개체가 자신의 API에서 선언되지 않은 것을 비밀리에 확보 할 수 있으므로 결과적으로 Singleton이 API를 병적 인 거짓말 쟁이로 만듭니다.
모든 싱글턴은 어디 갔어.의존성 삽입으로 인해 필요한 생성자에 인스턴스를 쉽게 가져올 수 있으므로 첫 번째 기사에서 비판 된 나쁜 글로벌 Singleton의 배후에있는 필요성이 완화됩니다.
혼란은 사람들이 싱글 톤 패턴의 실제 적용을 알지 못한다는 사실에 기인한다고 생각합니다. 나는 충분히 이것을 강조 할 수 없다. 싱글 톤아니전역을 래핑하는 패턴. 싱글 톤 패턴은이를 보장하기 위해서만 사용해야합니다.주어진 클래스의 하나의 인스턴스실행 중에 존재합니다.
사람들은 싱글 톤이 세계를 위해 사용하기 때문에 악하다고 생각합니다. 이것은 싱글 톤이 내려다 보인이 혼란 때문입니다. 싱글 톤과 글로벌을 혼동하지 마십시오. 그것이 의도 된 목적을 위해 사용된다면, 당신은 싱글 톤 패턴으로부터 극단적 인 이익을 얻을 것입니다.
setInstance
그 전에는 방법이 없었습니다.) 그게 문제는 아니지만 - "필요한" 싱글 톤은 캡슐화에 대한 괴상한 사실이나 가변적 인 전역 상태에 대한 잘못된 점을 알지 못했기 때문에 모든 사람에게 도움이되었다. 단일. 들. (그리고 예, 이것은 일어납니다.제비. 야생에서 보았던 거의 모든 싱글 톤은 디자인에 따라 변경 될 수 있으며, 종종 그렇게 당황 스럽습니다.) - cHaogoto
등.작업많은 경우에, 솔직히 말하면, "일한다" 충분하지 않습니다. 평범한 지혜를 버리기를 원한다면, 당신의 접근 방식이 얼마나 유용한지를 보여줄 수 있어야합니다....보다 나은기존 솔루션보다 그리고 아직 싱글 톤 패턴에 대한 사례를 보지 못했습니다. - cHaogetInstance
또는 유사하게 명명 된 방법을 사용하고 두 번째 인스턴스의 존재를 방지합니다. 솔직히, 그 시점에서, 당신은 심지어하나예. - cHao
싱글 톤에 대한 다소 나쁜 점 중 하나는 매우 쉽게 확장 할 수 없다는 것입니다. 기본적으로 어떤 종류의 빌드해야합니다.데코레이터 패턴또는 당신이 그들의 행동을 바꾸고 싶다면 그러한 것들. 또한 언젠가 한 가지 일을 여러 가지 방법으로 수행하려는 경우 코드를 배치하는 방법에 따라 변경하는 것이 다소 힘들 수 있습니다.
한가지주의 할 점은, 싱글 톤을 사용하는 경우, 싱글 톤을 직접 사용하지 않고 필요로하는 사람에게 전달하는 것입니다. 그렇지 않으면 싱글 톤이하는 일을 여러 가지 방법으로 수행하도록 선택한 경우, 각 클래스가 싱글 톤에 직접 액세스하는 경우 종속성을 포함하므로 변경하기가 어렵습니다.
그래서 기본적으로:
public MyConstructor(Singleton singleton) {
this.singleton = singleton;
}
오히려 :
public MyConstructor() {
this.singleton = Singleton.getInstance();
}
나는 이런 종류의 패턴이 있다고 믿는다.의존성 주입일반적으로 좋은 것으로 간주됩니다.
어떤 패턴이든간에 ... 그것에 대해 생각하고 주어진 상황에서 그 사용이 부적절하거나 아닌지 고려하십시오. 규칙은 보통 깨지게됩니다.패턴들생각없이 n w하게 적용해서는 안됩니다.
getInstance()
, (b)는 더 이상 사실이 아닙니다. - cHaogetInstance()
, Singleton 패턴과 일반적인 참조 사이의 유용한 차이점을 효과적으로 버렸습니다. 나머지 코드에 관한 한, 독신은 더 이상 재산이 아닙니다. 발신자 만getInstance()
얼마나 많은 인스턴스가 있는지 알고 있거나 심지어 신경을 써야합니다. 단 하나의 호출자만으로도 호출자가 참조를 저장하고 다시 사용하기보다는 클래스가 단일성을 안정적으로 시행 할 수 있도록 많은 노력과 유연성이 필요합니다. - cHao
싱글 톤 패턴 자체는 문제가되지 않습니다. 문제는 객체 지향 도구를 사용하여 OO 개념을 확실하게 파악하지 않고 소프트웨어를 개발하는 사람들이 패턴을 자주 사용한다는 것입니다. 이 상황에서 싱글 톤이 도입되면, 거의 사용하지 않을 때마다 도우미 메서드가 포함 된 관리하기 어려운 클래스로 성장하는 경향이 있습니다.
싱글 톤은 또한 테스트 관점에서 볼 때 문제입니다. 그들은 격리 된 단위 테스트를 작성하기가 어렵습니다.통제 반전(IoC) 및의존성 주입단위 테스트에 도움이되는 객체 지향 방식으로이 문제를 극복하기위한 패턴입니다.
안에쓰레기 수거환경 싱글 톤은 메모리 관리와 관련하여 신속하게 문제가 될 수 있습니다.
또한 싱글 톤이 동기화 문제뿐만 아니라 병목 현상이 될 수있는 멀티 스레드 시나리오가 있습니다.
싱글 톤은 정적 메서드를 사용하여 구현됩니다. 정적 메서드는 조롱되거나 스텁 될 수 없기 때문에 단위 테스트를 수행하는 사람들이 피할 수 있습니다. 이 사이트의 대부분의 사람들은 단위 테스트의 큰 지지자입니다. 그들을 피하기 위해 일반적으로 받아 들여지는 규칙은제어 반전무늬.
Singleton
수업. 그러나 이는 테스트 프로세스를 상당히 복잡하게 만듭니다. 하나는 이제 자유롭게 클래스를 언로드하거나 (대부분의 언어에서는 옵션이 아님) 각 테스트에 대해 새 VM을 시작할 수 있어야합니다 (읽기 : 테스트에 수천 배의 시간이 걸릴 수 있음). 하지만 두 가지 경우에 대한 의존성은Singleton
테스트의 모든 부분에서 현재 유출되고있는 구현 세부 사항입니다. - cHao
싱글 톤 또한 나쁘다.클러스터링. 그렇기 때문에 이제 응용 프로그램에 "정확히 하나의 싱글 톤"이 없습니다.
다음 상황을 고려하십시오. 개발자는 데이터베이스에 액세스하는 웹 응용 프로그램을 만들어야합니다. 동시 데이터베이스 호출이 서로 충돌하지 않도록하려면 스레드 저장을 작성하십시오SingletonDao
:
public class SingletonDao {
// songleton's static variable and getInstance() method etc. omitted
public void writeXYZ(...){
synchronized(...){
// some database writing operations...
}
}
}
따라서 응용 프로그램에서 단 하나의 싱글 톤만 존재하고 모든 데이터베이스가이 단 하나의SingletonDao
. 프로덕션 환경은 다음과 같습니다.
지금까지는 괜찮습니다.
이제 클러스터에서 웹 응용 프로그램의 여러 인스턴스를 설정하려고한다고 가정합니다. 자, 당신은 갑자기 다음과 같은 것을 가지고 있습니다 :
이상하게 들리지만이제 응용 프로그램에 많은 싱글 톤이 있습니다.. 그리고 그게 바로 싱글 톤이 될 수없는 것입니다 : 그것의 많은 것을 가지고 있습니다. 이 예제에서와 같이 데이터베이스에 동기화 된 호출을하려면이 작업이 특히 바람직하지 않습니다.
물론 이것이 싱글 톤의 나쁜 사용법의 예입니다. 그러나이 예제의 메시지는 다음과 같습니다. 응용 프로그램에 정확히 하나의 단일 인스턴스가 있다고 믿을 수는 없습니다. 특히 클러스터링과 관련해서는 그렇습니다.
독점은 악마이고 비 독서 / 가변 상태를 가진 싱글 톤은 '진짜'문제입니다 ...
읽고 나서싱글 톤은 병적 인 거짓말 쟁이입니다.제안 된대로제이슨의 대답나는이 제시된 가장 좋은 예를 제공하는 작은 맛있는 음식을 발견했다.방법싱글 톤은 종종 오용됩니다.
글로벌은 다음과 같은 이유로 좋지 않습니다.
- 에이. 네임 스페이스 충돌이 발생합니다.
- 비. 그것은 부당한 방식으로 국가를 노출시킵니다.
싱글 톤에 관해서
- 에이. 그들을 호출하는 명시적인 객체 지향 방법은 충돌을 방지하므로 다음과 같이 지정합니다. 문제가되지 않는다.
- 비. 상태가없는 싱글 톤 (공장과 같은)은 문제가되지 않습니다. 상태가있는 싱글 톤은 다시 불변이거나 한번 쓰고 많은 것을 읽는 (설정 / 등록 정보 파일) 두 가지 범주에 속할 수 있습니다. 이것들은 나쁘지 않습니다. 참조 소유자의 일종 인 변경 가능 싱글 톤은 당신이 말하는 사람입니다.
마지막 성명에서 그는 블로그의 '싱글 톤은 거짓말 쟁이'라는 개념을 언급하고 있습니다.
이것이 모노 폴리에 어떻게 적용됩니까?
독점 게임을 시작하려면 먼저 다음을 수행하십시오.
이제,정말이 독점 표준은 이상적입니다. 전매권에있는 패배는 독점이 돈에 관하여이기 때문에 삼키기 어렵다, 당신이 잃는 경우에 선수의 나머지가 근본적으로 게임을 끝내는 것을보아야하고, 손실은 보통 신속하고 분쇄된다. 따라서 규칙은 일반적으로 다른 플레이어를 희생시키면서 일부 플레이어의 이기심을 돕기 위해 어느 시점에서 비틀어집니다.
그래서 당신은 친구들 Bob, Joe, Ed와 독점을하고 있습니다. 당신은 신속하게 제국을 건설하고 기하 급수적 인 시장 점유율을 소비합니다. 상대방이 약해지고 피 냄새를 맡기 시작합니다 (비 유적으로). 당신의 친구 밥 (Bob)은 모든 돈을 가능한 한 많은 가치있는 자산으로 탈락시키지 만 예상했던대로 높은 투자 수익을 얻지 못하고 있습니다. 밥은 불운의 일격으로 보드 웍 (Boardwalk)에 상륙하며 게임에서 삭제됩니다.
이제 게임은 친숙한 주사위 굴리기에서 진지한 사업으로 바뀝니다. Bob은 실패의 예가되고 Joe와 Ed는 '그 사람'처럼 끝내기를 원하지 않습니다. 따라서 최고의 선수가되어 갑자기 적이됩니다. Joe와 Ed는 테이블 아래 거래, 뒤의 돈 주입, 저평가 된 하우스 스와핑 및 일반적으로 플레이어 중 한 명이 위로 올라갈 때까지 당신을 약화시킬 수있는 모든 것을 연습합니다.
그런 다음 그 중 하나가 승리하는 대신 프로세스가 시작됩니다. 갑자기, 유한 한 일련의 규칙들이 움직이는 표적이되고 게임은 생존자 이후의 모든 고화질 리얼리티 쇼의 기초를 구성 할 사회적인 상호 작용의 유형으로 변질됩니다. 왜, 규칙이 바뀌고 있고, 어떻게 / 왜 / 그들이 무엇을 나타 내기로되어 있는지에 대한 합의가없고, 더 중요한 것은 아무도 결정을 내리는 사람이 없다는 것입니다. 그 시점에서 모든 플레이어는 자신의 규칙과 혼란을 겪어서 두 명의 플레이어가 너무 피곤해서 뻔뻔 스러움을 유지하고 서서히 포기해야합니다.
따라서, 게임의 룰북이 정확하게 싱글 톤을 나타내면, 독점 룰북은 남용의 한 예가 될 것입니다.
이것이 프로그래밍에 어떻게 적용됩니까?
가변적 인 싱글 톤이 제시하는 확실한 스레드 안전성 및 동기화 문제를 제외하고 ... 여러 데이터 소스가 동시에 읽고 읽을 수있는 데이터 집합이 하나 있고 응용 프로그램 실행 수명 동안 존재할 경우, 아마 "지금 내가 올바른 유형의 데이터 구조를 사용하고 있는지 물어보십시오."라고 물어보십시오.
개인적으로 프로그래머가 응용 프로그램 내에서 트위스트 크로스 스레드 데이터베이스 저장소의 일종으로 싱글 톤을 악용하는 것을 보았습니다. 코드에서 직접 작업 해본 결과, (스레드 안전성을 높이기 위해 필요한 모든 스레드 잠금 때문에) 천천히 (동기화 버그의 예측할 수없는 / 간헐적 인 특성으로 인해) 작업 할 수있는 악몽과 '생산'조건 하에서 테스트하기가 거의 불가능합니다. 물론, 성능 문제의 일부를 극복하기 위해 폴링 / 시그널링을 사용하여 시스템을 개발할 수는 있지만 테스트를 통해 문제를 해결하지 못하고 '실제'데이터베이스가 훨씬 더 견고한 환경에서 동일한 기능을 수행 할 수있는 경우 왜 귀찮을까요? / 확장 방식.
싱글턴은만싱글 톤이 제공하는 것을 필요로한다면 옵션. object의 write-one 읽기 전용 인스턴스입니다. 같은 규칙이 객체의 속성 / 멤버와도 연계되어야합니다.
Singleton.getInstance()
. 리플렉션을 지원하는 언어는 하나의 트루 인스턴스가 저장된 필드를 설정하여이를 해결할 수 있습니다. 하지만 IMO에서는 다른 클래스의 비공개 상태로 원숭이를 돌리고 나면 테스트가 다소 신뢰성이 떨어집니다. - cHao
다른 답변 들과는 달리 나는 Singletons가 무엇이 잘못되었는지 이야기하고 싶지는 않습니다. 그러나 당신이 얼마나 강력하고 굉장한 지 보여주기 위해 그들은 올바르게 사용될 것입니다!
MyModel myModel = Factory.inject(MyModel.class);
지도를 만들 수 있습니다.MyModel
에TestMyModel
클래스를 상속하는 클래스MyModel
당신이 주사하게됩니다.TestMyModel
간통죄.내가 싱글 톤에 대해 말한 것처럼 싱글 톤은 하나의 인스턴스가 아닙니다.
Wikipedia Singleton_pattern을 참조하십시오.
그것은 또한 지나치게 사용되어 클래스의 유일한 인스턴스가 실제로 필요하지 않은 상황에서 불필요한 제한을 도입한다고 생각하는 사람들에 의해 반 패턴으로 간주됩니다. [1] [2] [3] [4]
참고 문헌 (해당 기사의 관련 참조 만)
싱글 톤이 나쁘다는 것에 대한 제 대답은 항상 "그들이 제대로하기가 어렵습니다"입니다. 언어의 기본 구성 요소 중 많은 부분은 컴퓨팅의 다른 측면 (로컬 호스트, 기본 경로, 가상 파일 시스템 등)의 구성 요소와 마찬가지로 싱글 톤 (클래스, 함수, 네임 스페이스 및 연산자)이며 우발적 인 것은 아닙니다. 그것들은 수시로 문제와 좌절을 일으키지 만, 많은 일들을 더 잘 수행 할 수 있습니다.
내가보기에 가장 큰 두 가지 원인은 다음과 같습니다. 글로벌 & 싱글 톤 폐쇄를 정의하지 못했습니다.
기본적으로 싱글 톤은 전역 변수로 이야기됩니다. 그러나 지구상의 모든 나쁜 점 (슬프게도, 전부는 아님)은 본질적으로 글로벌이 아니라, 어떻게 사용 하는가에 있습니다. Singletons도 마찬가지입니다. 실제로 "단일 인스턴스"가 "전 세계적으로 액세스 가능"하다는 것을 의미 할 필요는 없습니다. 그것은 더 자연스러운 부산물이며, 우리가 알고있는 모든 나쁜 점을 감안할 때, 글로벌 접근성을 개발하는 데 급히 서어서는 안됩니다. 프로그래머가 Singleton을 보게되면 인스턴스 메서드를 통해 직접 액세스하는 것처럼 보입니다. 대신 다른 객체처럼 탐색해야합니다. 대부분의 코드는 Singleton (loose coupling, right?)을 다루는 것을 인식하지 못합니다. 작은 코드 만 전역 객체처럼 객체에 액세스하면 많은 피해가 취소됩니다. 인스턴스 함수에 대한 액세스를 제한하여이를 적용하는 것이 좋습니다.
싱글 톤 컨텍스트도 매우 중요합니다. 싱글 톤의 특징을 정의하는 것은 "오직 하나"라는 것이지만, 진실은 일종의 컨텍스트 / 네임 스페이스 내에서 "유일한 것"이라는 것입니다. 그들은 일반적으로 스레드, 프로세스, IP 주소 또는 클러스터 당 하나이지만 프로세서, 기계, 언어 네임 스페이스 / 클래스 로더 / 무엇이든, 서브넷, 인터넷 등과 같이 하나씩이 될 수도 있습니다.
덜 일반적인 다른 실수는 싱글 톤 라이프 스타일을 무시하는 것입니다. 단지 하나만 존재하기 때문에 Singleton은 "항상 존재하고 항상 존재할 것입니다"라는 전능함을 의미하지 않으며, 일반적으로 바람직하지도 않습니다 (시작과 끝이없는 객체는 코드에서 모든 종류의 유용한 가정을 위반합니다. 상황이 가장 절실합니다.
이러한 실수를 피하면 싱글 톤은 여전히 PITA가 될 수 있습니다. 비트가 나올 때마다 최악의 문제가 크게 완화됩니다. Java Singleton은 클래스 로더 당 한 번 (스레드 안전성 정책이 필요함을 의미 함) 명시 적으로 정의되며 정의 된 작성 및 삭제 메소드 및 호출되는시기와 방법을 지정하는 라이프 사이클과 인스턴스 메소드가 가지고있는 라이프 사이클을 상상해보십시오. 패키지 보호이므로 일반적으로 다른 비 전역 객체를 통해 액세스됩니다. 여전히 문제의 잠재적 원천이지만, 확실히 적은 문제.
슬프게도, 싱글 톤을하는 법에 대한 좋은 예를 가르치는 것보다. 우리는 나쁜 예를 가르치고, 프로그래머들이 잠시 사용하지 못하게 한 다음 잘못된 디자인 패턴이라고 알려줍니다.
그것은 그 싱글 톤 자체가 나쁘지는 않지만 GoF 디자인 패턴입니다. 실제로 유효한 유일한 인수는 특히 테스트가 병렬로 실행되는 경우 GoF 디자인 패턴이 테스트와 관련이 없다는 것입니다.
코드에서 다음과 같은 방법을 적용하면 클래스의 단일 인스턴스를 사용할 수 있습니다.
싱글 톤으로 사용될 클래스가 인터페이스를 구현하는지 확인하십시오. 이를 통해 동일한 인터페이스를 사용하여 스텁 또는 모의 객체를 구현할 수 있습니다.
싱글 톤이 스레드로부터 안전한지 확인하십시오. 그것은 주어진 것입니다.
싱글 톤은 본질적으로 단순해야하며 지나치게 복잡하지 않아야합니다.
싱글 톤을 주어진 객체에 전달해야하는 응용 프로그램의 런타임 중에 해당 객체를 빌드하는 클래스 팩토리를 사용하고 클래스 팩토리가이를 필요로하는 클래스에 싱글 톤 인스턴스를 전달하게합니다.
테스트 중에 결정적인 동작을 보장하려면 실제 클래스 자체 또는 비헤이비어를 구현하는 스텁 / 모의 객체와 별도의 인스턴스로 싱글 톤 클래스를 만들고이를 필요로하는 클래스에 그대로 전달합니다. 테스트 도중 싱글 톤이 필요한 테스트 대상 객체를 만드는 클래스 요소를 사용하지 마십시오.이 요소는 단일 글로벌 인스턴스를 전달하므로 용도를 벗어납니다.
우리는 솔루션에서 싱글 톤을 사용하여 병렬 테스트 실행 스트림에서 결정 론적 동작을 테스트 할 수있는 많은 성공을 거두었습니다.
빈스 휴스턴나에게 합리적으로 보이는 다음 기준이 있습니다.
싱글 톤은 다음의 세 가지 기준 모두가 만족되는 경우에만 고려되어야합니다 :
- 단일 인스턴스의 소유권을 합리적으로 할당 할 수 없음
- 게으른 초기화가 바람직합니다.
- 달리 글로벌 액세스가 제공되지 않습니다.
단일 인스턴스의 소유권, 초기화 발생시기 및 방법, 전역 액세스가 문제가되지 않는다면 Singleton은 충분히 흥미롭지 않습니다.
나는 받아 들여진 응답에있는 4 개 점을 제시하고 싶으면, 누군가가 왜 나가 틀린 지 설명 할 수 있기를 바랍니다.
코드의 종속성을 왜 숨기고 있습니까? 이미 수십 개의 숨겨진 종속성 (C 런타임 호출, OS API 호출, 전역 함수 호출)이 있으며 단독 종속성을 쉽게 찾을 수 있습니다 (instance () 검색).
"세계를 무언가로 바꾸는 것이 코드의 냄새입니다." 싱글 톤 코드 냄새를 피하기 위해 무언가를 지나치는 이유는 무엇입니까?
싱글 톤을 피하기 위해 호출 스택에있는 10 개의 함수를 통해 객체를 전달하는 경우 그렇게 좋습니까?
Single Responsibility Principle : 저는 이것이 다소 모호하며 당신의 책임 정의에 달려 있다고 생각합니다. 관련 질문은, 왜 이것을 추가하는 것일까?특유한수업 문제에 대한 "책임"?
클래스에 객체를 전달하면 왜 그 객체를 클래스 내에서 싱글 톤으로 사용하는 것보다 더 밀접하게 결합됩니까?
국가 기밀 유지 기간이 변경되는 이유는 무엇입니까? 싱글 톤은 수동으로 만들거나 파괴 할 수 있으므로 컨트롤이 그대로 유지되므로 수명이 비 싱글 톤 개체의 수명과 같게 만들 수 있습니다.
단위 테스트에 관하여 :
싱글 톤은 순수주의의 관점에서 나쁘다.
우화적인 관점에서 볼 때,싱글 톤은 트레이드 오프 개발 시간 대 복잡성이다..
귀하의 신청서가 그만큼 변경되지 않을 것이라는 것을 알고 있다면 그들은 함께 갈 수 있습니다. 예상치 못한 방식으로 요구 사항이 변경되는 경우 리팩터링해야 할 수도 있음을 알고 있습니다 (대부분의 경우 매우 좋습니다).
싱글 톤은 때로는 또한 복잡합니다.단위 테스트.
패턴이 본질적으로 잘못 설정된 것은 없습니다. 모델의 일부 측면에 실제로 사용되고 있다고 가정하면 패턴에 아무런 문제가 없습니다.
반발은 과용에 기인한다고 생각합니다. 과용은 이해와 구현이 가장 쉬운 패턴이라는 사실 때문입니다.
싱글 톤은 패턴이며 다른 도구와 마찬가지로 사용하거나 악용 될 수 있습니다.
싱글 톤의 나쁜 부분은 일반적으로 사용자입니다 (또는 싱글 톤을 부적절하게 사용하도록 설계되지 않은 것에 대해서는이를 사용해야합니다). 가장 큰 범죄자는 가짜 글로벌 변수로 싱글 톤을 사용하고 있습니다.
로거 또는 데이터베이스 연결과 같은 싱글 톤을 사용하여 코드를 작성한 후 둘 이상의 로그 또는 하나 이상의 데이터베이스가 필요하다는 것을 알게되면 문제가 발생합니다.
싱글 톤은 정규 객체로 이동하기가 매우 어렵습니다.
또한 스레드 안전하지 않은 싱글 톤을 작성하는 것은 너무 쉽습니다.
싱글 톤을 사용하는 것보다 필요한 모든 유틸리티 객체를 함수에서 함수로 전달해야합니다. 이 모든 것을 도우미 객체로 래핑하면 다음과 같이 간단해질 수 있습니다.
void some_class::some_function(parameters, service_provider& srv)
{
srv.get<error_logger>().log("Hi there!");
this->another_function(some_other_parameters, srv);
}
싱글 톤 문제는 범위가 확대되는 문제이므로연결. 단일 인스턴스에 대한 액세스가 필요하고 다른 방법으로 수행 될 수있는 상황이 있음을 부인할 수 없습니다.
나는 이제 주변을 디자인하는 것을 선호한다.제어 반전(IoC) 용기에 넣고 수명이 용기에 의해 제어되도록합니다. 이렇게하면 단일 인스턴스가 있다는 사실을 알지 못하도록 인스턴스에 의존하는 클래스의 이점을 얻을 수 있습니다. 싱글 톤의 수명은 앞으로 변경 될 수 있습니다. 최근에 그런 예가 발생하면 단일 스레드에서 다중 스레드로 쉽게 조정할 수 있습니다.
FWIW, PIA의 경우 단위 테스트를 시도하면 PIA로 디버깅, 버그 수정 또는 향상을 시도합니다.
아무도 아직 말하지 않은 싱글 톤에 대해 한 가지 더 있습니다.
대부분의 경우 "싱글 톤"은 인터페이스의 특성보다는 일부 클래스의 구현 세부 사항입니다. Inversion of Control Container는이 특성을 클래스 사용자로부터 숨길 수 있습니다. 클래스를 싱글 톤으로 표시하면됩니다 (@Singleton
예를 들어 자바의 주석) 그게 다예요. IoCC는 나머지를 할 것입니다. 액세스가 이미 IoCC에 의해 관리되기 때문에 싱글 톤 인스턴스에 대한 전역 액세스를 제공 할 필요가 없습니다. 따라서 IoC 싱글 톤에는 아무런 문제가 없습니다.
GoF 싱글 톤은 IoC와 반대입니다. 싱글 톤은 getInstance () 메서드를 통해 인터페이스에서 "싱글 톤"을 노출해야하므로 위의 모든 것에서 고통받습니다.
싱글 톤은 나쁘지 않습니다. 세계적으로 유일하지 않은 세계적으로 고유 한 것을 만들 때만 안 좋은 일입니다.
그러나 "응용 프로그램 범위 서비스"(구성 요소가 상호 작용하는 메시징 시스템에 대해 생각해보십시오.) -이 단일 호출에 대한 CALLS, "SendMessage (...)"메서드가있는 "MessageQueue"클래스.
그 다음 장소에서 다음을 수행 할 수 있습니다.
MessageQueue.Current.SendMessage (새 MailArrivedMessage (...));
물론, 다음과 같이하십시오.
MessageQueue.Current.RegisterReceiver (this);
IMessageReceiver를 구현하는 클래스
너무 많은 사람들이 쓰레드 안전하지 않은 객체를 싱글 톤 패턴으로 넣는다. DataContext의 예를 보았습니다 (LINQ SQL)은 싱글 톤 패턴으로 처리되었지만 DataContext는 스레드로부터 안전하지 않으며 순전히 작업 단위 개체이기도합니다.
그것들은 기본적으로 객체 지향적 인 전역 변수이기 때문에 필요하지 않게 클래스를 디자인 할 수 있습니다.
여러 사람 (또는 팀)이 유사하거나 동일한 솔루션에 도달하면 패턴이 나타납니다. 많은 사람들이 여전히 원래 형태로 또는 팩토리 템플릿을 사용하여 싱글 톤을 사용합니다 (Alexandrescu의 Modern C ++ Design에서 좋은 토론). 객체의 수명을 관리하는 데있어 동시성과 난이도가 주요 장애물이며, 이전과 마찬가지로 쉽게 관리 할 수 있습니다.
모든 선택과 마찬가지로, 싱글 톤은 기복의 공정한 분배를 가지고 있습니다. 나는 그들이 적당히 사용할 수 있다고 생각합니다. 특히 응용 프로그램 수명에서 살아남은 객체의 경우에 특히 그렇습니다. 그들이 닮은 (그리고 아마도 그럴듯한) 사실은 아마도 순수 주의자들을 출발 시켰을 것이다.
첫째, 수업 및 그 공동 작업자는 먼저 착수 자에 초점을 맞추기보다는 의도 된 목적을 수행해야합니다. 수명주기 관리 (인스턴스가 범위를 벗어날 때 인스턴스가 만들어지면)는 클래드 책임의 일부가되어서는 안됩니다. 이를위한 가장 좋은 방법은 종속성 주입을 사용하여 종속성을 관리하기위한 새로운 구성 요소를 만들거나 구성하는 것입니다.
종종 소프트웨어는 더 복잡해지면서 서로 다른 상태의 "싱글 톤"클래스의 여러 독립 인스턴스를 갖는 것이 합리적입니다. 이런 경우에는 싱글 톤을 잡기위한 코드를 작성하는 것이 잘못되었습니다. 작은 단순한 시스템에서는 Singleton.getInstance ()를 사용하는 것이 좋지만 동일한 클래스의 다른 인스턴스가 필요한 경우에는 작동하지 않습니다.
어떤 클래스도 싱글 톤으로 생각해서는 안되며, 오히려 그것의 사용법이나 의존성을 구성하는 데 어떻게 사용되어야 하는지를 설명해야합니다. 빠르고 간단하게 말하자면 이것은 중요하지 않습니다. 단지 코딩 만하면 파일 경로가 중요하지 않다고 말하면서 더 큰 애플리케이션의 경우 DI를 사용하여 그러한 종속성을 계산하고보다 적절한 방법으로 관리해야합니다.
테스트에서 싱글 톤이 발생시키는 문제는 하드 코딩 된 단일 사용 사례 / 환경의 증상입니다. 테스트 스위트와 많은 테스트는 각각 개별적이며 싱글 톤의 하드 코딩과 호환되지 않는 별도의 테스트입니다.