1798

그만큼싱글 톤 패턴완전 유료 회원입니다.GoF'에스패턴 책,하지만 최근에는 개발자 세계에 의해 고아가 된 것 같습니다. 나는 아직도 많은 싱글 톤을 사용한다.공장 수업, 그리고 당신이 멀티 스레딩 문제 (어떤 클래스와 같은)에 대해 조심해야 할 때, 나는 왜 그렇게 끔찍한 지 알지 못한다.

Stack Overflow는 특히 싱글 톤이 악하다고 동의하는 것으로 추측됩니다. 왜?

귀하의 답변을 "사실, 참고 문헌 또는 특정 전문 지식"


  • 싱글 톤 디자인을 사용하면 최근에 코드를 수정하려고 시도하면서 나를 불태 웠습니다. 내가 자유 시간에 그것을 할 때, 나는 이것을 너무 리팩토링하기에는 게으르다. 생산성에 나쁜 소식. - Marcin
  • 많은 ' 해답을 찾을 수는 있지만 패턴이 좋은 시점과 좋지 않은 점을 대비하여 좋은 사례를보고 싶습니다. - DGM
  • 나는 몇 달 전에이 주제에 대한 블로그 글을 썼다.jalf.dk/blog/2010/03/…- 내가 그 말을 철저하게 말하게 해줘. 싱글 톤이 올바른 해결책 인 단일 상황을 개인적으로 생각할 수는 없습니다. 그러한 상황이 존재하지 않는다는 것을 의미하지는 않지만 ... 희귀 한 사람들을 삼가하는 것은 삼가면서 말하는 것입니다. - jalf
  • @ AdamSmith 그것은 당신을 의미하지 않습니다.있다~,하지만 너를 의미한다.양철통그런 식으로 액세스하십시오. 그런 식으로 액세스하지 않으려는 경우, 처음에는 그것을 싱글 톤으로 만들 필요가 거의 없습니다. 그래서 당신의 주장은 사실상 " 싱글 톤을 만들 때 해를 끼치 지 않습니다.      그것은 싱글 톤으로. 그래, 좋아. 내 차를 몰지 않으면 내 차도 오염되지 않습니다. 그러나 처음에는 자동차를 사지 않는 것이 더 쉽습니다. ;) (전체 공개 : 나는 실제로 차를 가지고 있지 않다) - jalf
  • 전체 주제의 최악의 부분은 싱글 톤을 싫어하는 사람들이 무엇을 대신 사용해야하는지에 대한 구체적인 제안을하는 경우는 드물다. 예를 들어,이 SO 기사를 통해 저널 기사 및 자체 게시 된 블로그에 대한 링크를 통해 왜아니싱글 톤을 사용하는 것이지만 (모두 훌륭한 이유가 있지만) 대체율이 매우 낮습니다. 손을 많이 뻗쳤습니다. 새로운 프로그래머에게 싱글 톤을 사용하지 않는 이유를 가르치려는 사람들은 좋은 제 3 자 반 대조표를 지적하지 않고 인위적인 사례만을 지적합니다. 지친 것입니다. - Ti Strga

30 답변


1182

브라이언 버튼 (Brian Button)

  1. 그들은 일반적으로 글로벌 인스턴스로 사용됩니다, 왜 그렇게 나쁜가요? 인터페이스를 통해 코드를 노출하는 대신 코드에서 응용 프로그램의 종속성을 숨길 수 있기 때문입니다. 세계를 무언가로 만들어서 지나치지 않도록하십시오.코드 냄새.

  2. 그들은단일 책임 원칙: 자신의 창조와 수명주기를 통제한다는 사실 덕분입니다.

  3. 그들은 본질적으로 코드를 단단히 만듭니다.결합 된. 이로 인해 많은 경우 테스트가 다소 어려워졌습니다.

  4. 응용 프로그램의 수명 동안 상태를 유지합니다. 테스트에 대한 또 다른 히트는 테스트를 주문해야하는 상황으로 끝날 수 있기 때문에 단위 테스트에 큰 문제가되지 않습니다. 왜? 왜냐하면 각 단위 테스트는 다른 단위 테스트와 독립적이어야하기 때문입니다.


  • 나는 동의하지 않는다. 댓글은 600 자 밖에 허용되지 않으므로, 블로그 게시물을 작성하여 이에 대한 의견을 말하려면 아래 링크를 참조하십시오.jorudolph.wordpress.com/2009/11/22/singleton-considerations - Johannes Rudolph
  • 포인트 1과 4에서 싱글 톤은 유용하며 사실 캐싱 데이터 (특히 DB에서)에 거의 완벽하다고 생각합니다. 성능 향상은 단위 테스트 모델링과 관련된 복잡성을 훨씬 앞당겨줍니다. - Dai Bok
  • @Dai Bok : "캐싱 데이터 (특히 DB에서)" 프록시 패턴을 사용하여 ... - paxos1977
  • 와우, 좋은 반응. 나는 여기에 지나치게 공격적인 말씨를 사용했을 것입니다. 그래서 부정적인 질문에 답하는 것을 명심하십시오. 내 대답은 '반 패턴'이라는 짧은 목록이었습니다. 이는 나쁜 싱글 톤 사용으로 발생합니다. 전체 공개; 나도 때때로 Singleton을 사용한다. 싱글 톤이 좋은 생각으로 간주 될 수있는 훌륭한 포럼을 만들 수있는 중립적 인 질문이 있습니다. 예를 들어,stackoverflow.com/questions/228164/… - Jim Burger
  • 다중 스레드 환경에서 캐싱에 적합하지 않습니다. 제한된 리소스에서 여러 스레드가 충돌하는 캐시를 쉽게 물리 칠 수 있습니다. [싱글 톤에 의해 유지] - monksy

414

싱글 톤은 하나의 문제를 해결합니다.

자원 경합.

리소스가 있다면

(1)는 하나의 인스턴스 만 가질 수 있습니다.

(2) 당신은 그 단일 인스턴스를 관리해야합니다.

네가 필요해.하나씩 일어나는 것.

예는 많지 않습니다. 로그 파일은 큰 파일입니다. 단일 로그 파일을 그냥 버리고 싶지는 않습니다. 플러시, 동기화 및 제대로 닫으려고합니다. 이것은 관리해야하는 단일 공유 자원의 예입니다.

싱글 톤이 필요한 경우는 거의 없습니다. 그들이 나쁜 이유는 그들이 기분이 좋다는 것입니다.글로벌그리고 그들은 GoF의 완전히 지불 된 회원입니다.디자인 패턴책.

글로벌이 필요하다고 생각하면 아마도 끔찍한 디자인 실수를 저지르고있을 것입니다.


  • 하드웨어 또한 좋은 예입니다. 임베디드 시스템에는 싱글 톤을 사용할 수있는 많은 하드웨어가 있습니다. < grin > - Jeff
  • 전적으로 동의합니다. "이 관행이 좋지 않습니다 "라고 많은 결정을했습니다. 연습이 그 자리를 차지할 수 있다는 것을 아무런 인식없이 떠 다니는 이야기. 흔히 연습은 단지 "불량"이다. 그것은 종종 잘못 사용 되었기 때문입니다. Singleton 패턴이 적절하게 적용되는 한 본질적으로 Singleton 패턴에는 문제가 없습니다. - Damovisa
  • 진짜, by-principle 싱글 톤은 매우 드뭅니다 (물론 프린터 대기열은 하나도 아니며 로그 파일도 없습니다 - log4j 참조). 종종 하드웨어는 원칙보다는 우연에 의한 싱글 톤입니다. PC에 연결된 모든 하드웨어는 여러 대의 모니터, 마우스, 프린터, 사운드 카드를 생각할 때 우연히도 우연의 일치입니다. 500mio $ 입자 검출기조차도 우연의 일치와 예산 제약에 의한 싱글 톤입니다. 소프트웨어에서는 적용 할 수 없으므로 싱글 톤이 필요하지 않습니다. 통신에서 전화 번호도 실제 전화도 싱글 톤이 아닙니다 (ISDN, 콜센터). - digitalarbeiter
  • 하드웨어에는 다양한 리소스의 인스턴스가 하나만있을 수 있지만 하드웨어는 소프트웨어가 아닙니다. 개발 보드의 단일 직렬 포트를 싱글 톤으로 모델링해야하는 이유는 없습니다. 실제로, 그것을 모델링하면 포트가 2 개있는 새로운 보드로 포팅하는 것이 더 어려워집니다! - dash-tom-bang
  • 따라서 두 개의 동일한 클래스를 작성하여 많은 코드를 복제하면 두 개의 싱글 톤을 두 개의 포트로 나타낼 수 있습니다. 두 개의 글로벌 SerialPort 객체를 사용하는 것은 어떨까요? 하드웨어를 클래스로 모델링하지 않으시겠습니까? 왜 글로벌 액세스를 의미하는 싱글 톤을 사용합니까? 너를 원하니?...마다코드에서 직렬 포트에 액세스 할 수 있습니까? - jalf

315

일부 코딩 snobs 그냥 영광스러운 세계를 내려다 보면서. 많은 사람들이 싫어하는 것과 같은 방식으로goto성명을 사용하는 아이디어를 싫어하는 사람들이있다.글로벌. 몇 명의 개발자가 특별한 길이로 나가는 것을 보았습니다.글로벌왜냐하면 그들은 하나의 실패를 인정하는 것으로 간주했기 때문입니다. 이상하지만 사실.

실제로하나씩 일어나는 것패턴은 개념의 툴킷에서 유용한 부분 인 프로그래밍 기법 일뿐입니다. 때로는 이상적인 솔루션임을 알게 될 수도 있습니다. 하지만 그것을 사용하면 자랑 스러울 수 있습니다.디자인 패턴그냥 사용하기를 거부 한 것처럼 바보입니다.글로벌.


  • 싱글 톤 (Singleton)에서 볼 수있는 실패는 사람들이 어떻게 든 "더 낫다"때문에 전역 변수 대신에 그것을 사용한다는 것입니다. 문제는 (내가 보았 듯이) 싱글 톤이 이러한 경우에 테이블로 가져 오는 것들은 무의미하다는 것입니다. 예를 들어 생성자를 실제로 사용하지 않는 경우에도 비 구속 (non-singleton)으로 구현하는 것은 처음부터 처음 사용하는 것은 쉽습니다. - dash-tom-bang
  • 이유 "우리" 그 (것)들을 내려다 보는 것은 " 우리 " 매우 자주 자주 잘못 사용되고 너무 자주 사용되는 것을 봅니다. "우리" 그들이 원인의 그들의 장소가다는 것을 아십시오. - Bjarke Freund-Hansen
  • @Phil, 당신은 "때로는 이상적인 솔루션이라는 것을 알게 될 것입니다."라고 말했습니다. 좋아.어느싱글 톤이 유용하다고 생각합니까? - Pacerier
  • @Pacerier는 다음 조건이 모두 충족 될 때마다 : (1) 무언가 하나만 필요합니다. (2) 많은 메소드 호출에서 하나의 인수를 인수로 전달해야합니다. (3) 인수를 기꺼이 받아 들일 수 있습니다. 언젠가 리팩터링 할 필요가있는 기회. 어디서나 코드를 전달하지 않아 코드의 크기와 복잡성이 즉각적으로 줄어들 것입니다. - antinome
  • 이 답변에 아무런 답변이 없다고 말하면 '때로는 적합 할 수도 있고 그렇지 않을 수도 있습니다.'라고 말하면됩니다. 좋아요,하지만 왜, 언제 요? 이 답변을검토에 대한 논쟁? - Guildenstern

205

Google의 Misko Hevery는 정확하게이 주제에 대한 흥미로운 기사를 가지고 있습니다 ...

싱글 톤은 병적 인 거짓말 쟁이입니다.는 싱글 톤을 사용하여 종속성 체인을 파악하고 응용 프로그램을 시작하거나 테스트하는 것을 어렵게하는 방법을 보여주는 단위 테스트 예제가 있습니다. 그것은 학대의 상당히 극단적 인 예이지만 그가 만드는 요점은 여전히 유효합니다.

싱글 톤은 전체적인 상태에 불과합니다. 전역 상태를 사용하면 개체가 자신의 API에서 선언되지 않은 것을 비밀리에 확보 할 수 있으므로 결과적으로 Singleton이 API를 병적 인 거짓말 쟁이로 만듭니다.

모든 싱글턴은 어디 갔어.의존성 삽입으로 인해 필요한 생성자에 인스턴스를 쉽게 가져올 수 있으므로 첫 번째 기사에서 비판 된 나쁜 글로벌 Singleton의 배후에있는 필요성이 완화됩니다.


  • 주제에 관한 미코의 기사는 현재 그 문제를 해결하는 데 가장 좋은 방법입니다. - Chris Mayer
  • 첫 번째 링크는 싱글 톤 문제를 실제로 해결하지는 않지만 클래스 내부의 정적 종속성을 가정합니다. 매개 변수를 전달하여 주어진 예제를 수정할 수도 있지만 여전히 싱글 톤을 사용합니다. - DGM
  • @DGM : 정확히 말하자면, '이론적 근거'와 '이론적 근거'사이에는 엄청난 논리적 구분이있다. 기사의 일부와 '싱글 톤'이 원인입니다. 부품. - Harper Shelby
  • Misko의 신용 카드 도움말은극단이 패턴의 오용 예. - Alex
  • 두 번째 기사 Singleton을 읽는 것은 실제로 설명 된 객체 모델의 일부입니다. 그러나 전역 적으로 액세스 할 수있는 대신 Factory 객체에 대해 private입니다. - FruitBreak

106

혼란은 사람들이 싱글 톤 패턴의 실제 적용을 알지 못한다는 사실에 기인한다고 생각합니다. 나는 충분히 이것을 강조 할 수 없다. 싱글 톤아니전역을 래핑하는 패턴. 싱글 톤 패턴은이를 보장하기 위해서만 사용해야합니다.주어진 클래스의 하나의 인스턴스실행 중에 존재합니다.

사람들은 싱글 톤이 세계를 위해 사용하기 때문에 악하다고 생각합니다. 이것은 싱글 톤이 내려다 보인이 혼란 때문입니다. 싱글 톤과 글로벌을 혼동하지 마십시오. 그것이 의도 된 목적을 위해 사용된다면, 당신은 싱글 톤 패턴으로부터 극단적 인 이익을 얻을 것입니다.


  • 앱 전체에서 사용할 수있는 인스턴스는 무엇입니까? 오.글로벌. "싱글 톤은아니전역을 래핑하는 패턴 " 순진하거나 오해의 소지가있는정의에 의한패턴은 전역 인스턴스 주위에 클래스를 래핑합니다. - cHao
  • 물론 애플리케이션이 시작될 때 하나의 클래스 인스턴스를 자유롭게 생성하고 인터페이스를 통해 그 인스턴스를 사용하는 인스턴스에 인스턴스를 삽입 할 수 있습니다. 구현시 하나만있을 수 있다는 사실을 염두에 두지 않아야합니다. - Scott Whitlock
  • @Dainius : 결국에는 그렇지 않습니다. 물론 인스턴스를 다른 인스턴스로 임의로 바꾸지 않아도됩니다. (얼굴을 유도하는 순간을 제외하고. 실제로 보았습니다.setInstance그 전에는 방법이 없었습니다.) 그게 문제는 아니지만 - "필요한" 싱글 톤은 캡슐화에 대한 괴상한 사실이나 가변적 인 전역 상태에 대한 잘못된 점을 알지 못했기 때문에 모든 사람에게 도움이되었다. 단일. 들. (그리고 예, 이것은 일어납니다.제비. 야생에서 보았던 거의 모든 싱글 톤은 디자인에 따라 변경 될 수 있으며, 종종 그렇게 당황 스럽습니다.) - cHao
  • @Dainius : 우리는 이미 가지고 있습니다. " 상속에 우선 구성 " 꽤 오래되었습니다. 상속시~이다.명백히 최상의 솔루션이지만, 물론 무료로 사용할 수 있습니다. 싱글 톤, 전역, 스레딩,goto등.작업많은 경우에, 솔직히 말하면, "일한다" 충분하지 않습니다. 평범한 지혜를 버리기를 원한다면, 당신의 접근 방식이 얼마나 유용한지를 보여줄 수 있어야합니다....보다 나은기존 솔루션보다 그리고 아직 싱글 톤 패턴에 대한 사례를 보지 못했습니다. - cHao
  • 우리가 과거를 이야기하지 않도록 전 세계적으로 사용 가능한 인스턴스에 대해서만 이야기하는 것이 아닙니다. 많은 경우가 있습니다. 제가 말하고있는 것은 (특히 "capital-S Singleton"이라고 할 때) GoF의 싱글 톤 패턴입니다. 싱글 글로벌 인스턴스를 클래스 자체에 임베드하고, 클래스를 통해 노출합니다.getInstance또는 유사하게 명명 된 방법을 사용하고 두 번째 인스턴스의 존재를 방지합니다. 솔직히, 그 시점에서, 당신은 심지어하나예. - cHao

70

싱글 톤에 대한 다소 나쁜 점 중 하나는 매우 쉽게 확장 할 수 없다는 것입니다. 기본적으로 어떤 종류의 빌드해야합니다.데코레이터 패턴또는 당신이 그들의 행동을 바꾸고 싶다면 그러한 것들. 또한 언젠가 한 가지 일을 여러 가지 방법으로 수행하려는 경우 코드를 배치하는 방법에 따라 변경하는 것이 다소 힘들 수 있습니다.

한가지주의 할 점은, 싱글 톤을 사용하는 경우, 싱글 톤을 직접 사용하지 않고 필요로하는 사람에게 전달하는 것입니다. 그렇지 않으면 싱글 톤이하는 일을 여러 가지 방법으로 수행하도록 선택한 경우, 각 클래스가 싱글 톤에 직접 액세스하는 경우 종속성을 포함하므로 변경하기가 어렵습니다.

그래서 기본적으로:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

오히려 :

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

나는 이런 종류의 패턴이 있다고 믿는다.의존성 주입일반적으로 좋은 것으로 간주됩니다.

어떤 패턴이든간에 ... 그것에 대해 생각하고 주어진 상황에서 그 사용이 부적절하거나 아닌지 고려하십시오. 규칙은 보통 깨지게됩니다.패턴들생각없이 n w하게 적용해서는 안됩니다.


  • ㅎ, 당신이 어디서나 이것을한다면, 어디에서나 싱글 톤에 대한 참조를 전달해야하므로 더 이상 싱글 톤이 없습니다. :) (어느 것이 보통 IMO 좋은 일입니다.) - Bjarke Freund-Hansen
  • @ BjarkeFreund-Hansen - 말도 안돼, 그게 무슨 소리 야? 싱글 톤은 단순히 한 번 instatiiated 클래스의 인스턴스입니다. 그러한 싱글 톤을 참조하는 것은 실제 객체를 복사하지 않고 방금 참조합니다 - 당신은 여전히 동일한 객체를 가지고 있습니다 (읽기 : Singleton). - M. Mimpen
  • @ M.Mimpen : 아니, 자본 -S 싱글 톤 (여기에서 논의되는 내용)은 (a)보증하나의 인스턴스 만 존재할 것이며, (b) 클래스 자체의 기본 제공 전역 액세스 지점을 통해 액세스됩니다. 아무 것도 부르지 말라고 선언했다면getInstance(), (b)는 더 이상 사실이 아닙니다. - cHao
  • @cHao 나는 Bjarke Freund-Hansen에게 내가하는 누구에게 당신을 따르지 않거나 이해하지 못한다. Bjarke는 싱글 톤에 대한 여러 가지 참조를 사용하면 몇 개의 싱글 톤을 가질 수 있다고 말합니다. 깊은 사본이 없기 때문에 그것은 사실이 아닙니다. - M. Mimpen
  • @ M.Mimpen : 나는 의미 론적 효과를 더 많이 언급하기 위해 그의 의견을 듣는다. 당신이 전화를 무법자로 만들면getInstance(), Singleton 패턴과 일반적인 참조 사이의 유용한 차이점을 효과적으로 버렸습니다. 나머지 코드에 관한 한, 독신은 더 이상 재산이 아닙니다. 발신자 만getInstance()얼마나 많은 인스턴스가 있는지 알고 있거나 심지어 신경을 써야합니다. 단 하나의 호출자만으로도 호출자가 참조를 저장하고 다시 사용하기보다는 클래스가 단일성을 안정적으로 시행 할 수 있도록 많은 노력과 유연성이 필요합니다. - cHao

65

싱글 톤 패턴 자체는 문제가되지 않습니다. 문제는 객체 지향 도구를 사용하여 OO 개념을 확실하게 파악하지 않고 소프트웨어를 개발하는 사람들이 패턴을 자주 사용한다는 것입니다. 이 상황에서 싱글 톤이 도입되면, 거의 사용하지 않을 때마다 도우미 메서드가 포함 된 관리하기 어려운 클래스로 성장하는 경향이 있습니다.

싱글 톤은 또한 테스트 관점에서 볼 때 문제입니다. 그들은 격리 된 단위 테스트를 작성하기가 어렵습니다.통제 반전(IoC) 및의존성 주입단위 테스트에 도움이되는 객체 지향 방식으로이 문제를 극복하기위한 패턴입니다.

안에쓰레기 수거환경 싱글 톤은 메모리 관리와 관련하여 신속하게 문제가 될 수 있습니다.

또한 싱글 톤이 동기화 문제뿐만 아니라 병목 현상이 될 수있는 멀티 스레드 시나리오가 있습니다.


  • 나는 그것이 오래 된 스레드임을 압니다. 안녕하세요 @ Kimoz u는 말했다 : - 싱글 톤은 신속하게 메모리 관리와 관련하여 문제가 될 수 있습니다. 어떤 종류의 문제가 싱글 톤 & 가비지 컬렉션. - Thomas
  • @Kimoz, 질문은 묻습니다." 왜 싱글 톤 패턴이 그 자체로 문제가되지 않습니까? "당신은 그 요점을 되풀이하면서도 싱글 톤 패턴의 단일 유즈 케이스를 제공하지 않았습니다. - Pacerier
  • @Thomas. 정의에 의한 싱글 톤은 단 하나의 인스턴스에만 있기 때문에. 따라서 null에 대한 유일한 참조를 할당하는 것은 종종 복잡합니다. 할 수는 있지만 앱에서 싱글 톤이 사용되지 않는 시점을 완전히 제어한다는 의미입니다. 드문 경우이지만 싱글 애호가가 찾고있는 것과는 정반대입니다. 단일 인스턴스를 만드는 간단한 방법입니다.항상얻기 쉬운. Guice 나 Dagger와 같은 일부 DI 프레임 워크에서는 싱글 톤을 제거 할 수 없으며 메모리에서 영원히 유지됩니다. (컨테이너 제공 싱글 톤은 가정용보다 훨씬 낫지 만). - Snicolas

52

싱글 톤은 정적 메서드를 사용하여 구현됩니다. 정적 메서드는 조롱되거나 스텁 될 수 없기 때문에 단위 테스트를 수행하는 사람들이 피할 수 있습니다. 이 사이트의 대부분의 사람들은 단위 테스트의 큰 지지자입니다. 그들을 피하기 위해 일반적으로 받아 들여지는 규칙은제어 반전무늬.


  • 그것은 객체 (유닛), 함수 (유닛), 전체 라이브러리 (유닛)를 테스트 할 수 있지만 클래스에서 정적 인 것 (유닛)으로 실패 할 수있는 유닛 테스트의 문제와 비슷하게 들립니다. - v010dya
  • 어쨌든 모든 외부 참조를 moc한다고 생각하지 않으세요? 그렇다면 moc singleton에 어떤 문제가 있는지, 그렇지 않다면 정말로 단위 테스트를하고 있습니까? - Dainius
  • @Dainius : 조롱인스턴스수업 조롱보다 문제가 적습니다. 나머지 응용 프로그램에서 테스트중인 클래스를 추출하여 가짜로 테스트 할 수 있습니다Singleton수업. 그러나 이는 테스트 프로세스를 상당히 복잡하게 만듭니다. 하나는 이제 자유롭게 클래스를 언로드하거나 (대부분의 언어에서는 옵션이 아님) 각 테스트에 대해 새 VM을 시작할 수 있어야합니다 (읽기 : 테스트에 수천 배의 시간이 걸릴 수 있음). 하지만 두 가지 경우에 대한 의존성은Singleton테스트의 모든 부분에서 현재 유출되고있는 구현 세부 사항입니다. - cHao
  • Powermock은 정적 물건을 조롱 할 수 있습니다. - Snicolas
  • 객체 조롱은 실제 객체를 만드는 것을 의미합니까? mocking이 실제 객체를 생성하지 않으면 클래스가 싱글 톤인지 또는 정적인지 여부가 중요한 이유는 무엇입니까? - Arun Raaj

42

싱글 톤 또한 나쁘다.클러스터링. 그렇기 때문에 이제 응용 프로그램에 "정확히 하나의 싱글 톤"이 없습니다.

다음 상황을 고려하십시오. 개발자는 데이터베이스에 액세스하는 웹 응용 프로그램을 만들어야합니다. 동시 데이터베이스 호출이 서로 충돌하지 않도록하려면 스레드 저장을 작성하십시오SingletonDao:

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

따라서 응용 프로그램에서 단 하나의 싱글 톤만 존재하고 모든 데이터베이스가이 단 하나의SingletonDao. 프로덕션 환경은 다음과 같습니다.Single Singleton

지금까지는 괜찮습니다.

이제 클러스터에서 웹 응용 프로그램의 여러 인스턴스를 설정하려고한다고 가정합니다. 자, 당신은 갑자기 다음과 같은 것을 가지고 있습니다 :

Many singletons

이상하게 들리지만이제 응용 프로그램에 많은 싱글 톤이 있습니다.. 그리고 그게 바로 싱글 톤이 될 수없는 것입니다 : 그것의 많은 것을 가지고 있습니다. 이 예제에서와 같이 데이터베이스에 동기화 된 호출을하려면이 작업이 특히 바람직하지 않습니다.

물론 이것이 싱글 톤의 나쁜 사용법의 예입니다. 그러나이 예제의 메시지는 다음과 같습니다. 응용 프로그램에 정확히 하나의 단일 인스턴스가 있다고 믿을 수는 없습니다. 특히 클러스터링과 관련해서는 그렇습니다.


  • 싱글 톤을 구현하는 방법을 모르는 경우 그렇게하지 않아야합니다. 자신이하는 일을 알지 못한다면 먼저 그 일을 찾아야하며 그 후에 만 필요한 일을해야합니다. - Dainius
  • 이것은 재미있다, 나는 질문이있다. 그렇다면 서로 다른 머신 / JVM에있는 싱글 톤이 단일 데이터베이스에 연결하는 경우 정확히 어떤 문제가 발생합니까? 싱글 톤 범위는 해당 특정 JVM에만 해당되며 클러스터에서도 여전히 유효합니다. 우리의 의도가 응용 프로그램 전반에 걸쳐 하나의 객체이기 때문에 이러한 특정 상황이 잘못되었다고 철학적으로 말하기보다는이 배열로 인해 발생할 수있는 기술적 문제를 보게되어 기쁩니다. - Saurabh Patil

34

  1. 그것은 쉽게 전역 변수로 사용됩니다.
  2. 싱글 톤에 의존하는 클래스는 단위 테스트가 상대적으로 더 어렵습니다.


30

독점은 악마이고 비 독서 / 가변 상태를 가진 싱글 톤은 '진짜'문제입니다 ...

읽고 나서싱글 톤은 병적 인 거짓말 쟁이입니다.제안 된대로제이슨의 대답나는이 제시된 가장 좋은 예를 제공하는 작은 맛있는 음식을 발견했다.방법싱글 톤은 종종 오용됩니다.

글로벌은 다음과 같은 이유로 좋지 않습니다.

  • 에이. 네임 스페이스 충돌이 발생합니다.
  • 비. 그것은 부당한 방식으로 국가를 노출시킵니다.

싱글 톤에 관해서

  • 에이. 그들을 호출하는 명시적인 객체 지향 방법은 충돌을 방지하므로 다음과 같이 지정합니다. 문제가되지 않는다.
  • 비. 상태가없는 싱글 톤 (공장과 같은)은 문제가되지 않습니다. 상태가있는 싱글 톤은 다시 불변이거나 한번 쓰고 많은 것을 읽는 (설정 / 등록 정보 파일) 두 가지 범주에 속할 수 있습니다. 이것들은 나쁘지 않습니다. 참조 소유자의 일종 인 변경 가능 싱글 톤은 당신이 말하는 사람입니다.

마지막 성명에서 그는 블로그의 '싱글 톤은 거짓말 쟁이'라는 개념을 언급하고 있습니다.

이것이 모노 폴리에 어떻게 적용됩니까?

독점 게임을 시작하려면 먼저 다음을 수행하십시오.

  • 모두가 동일한 페이지에 있도록 규칙을 먼저 설정합니다.
  • 모두가 게임 시작시 동등한 출발을한다.
  • 혼란을 피하기 위해 오직 한 세트의 규칙 만 제시된다.
  • 규칙은 게임 내내 변경 될 수 없다.

이제,정말이 독점 표준은 이상적입니다. 전매권에있는 패배는 독점이 돈에 관하여이기 때문에 삼키기 어렵다, 당신이 잃는 경우에 선수의 나머지가 근본적으로 게임을 끝내는 것을보아야하고, 손실은 보통 신속하고 분쇄된다. 따라서 규칙은 일반적으로 다른 플레이어를 희생시키면서 일부 플레이어의 이기심을 돕기 위해 어느 시점에서 비틀어집니다.

그래서 당신은 친구들 Bob, Joe, Ed와 독점을하고 있습니다. 당신은 신속하게 제국을 건설하고 기하 급수적 인 시장 점유율을 소비합니다. 상대방이 약해지고 피 냄새를 맡기 시작합니다 (비 유적으로). 당신의 친구 밥 (Bob)은 모든 돈을 가능한 한 많은 가치있는 자산으로 탈락시키지 만 예상했던대로 높은 투자 수익을 얻지 못하고 있습니다. 밥은 불운의 일격으로 보드 웍 (Boardwalk)에 상륙하며 게임에서 삭제됩니다.

이제 게임은 친숙한 주사위 굴리기에서 진지한 사업으로 바뀝니다. Bob은 실패의 예가되고 Joe와 Ed는 '그 사람'처럼 끝내기를 원하지 않습니다. 따라서 최고의 선수가되어 갑자기 적이됩니다. Joe와 Ed는 테이블 아래 거래, 뒤의 돈 주입, 저평가 된 하우스 스와핑 및 일반적으로 플레이어 중 한 명이 위로 올라갈 때까지 당신을 약화시킬 수있는 모든 것을 연습합니다.

그런 다음 그 중 하나가 승리하는 대신 프로세스가 시작됩니다. 갑자기, 유한 한 일련의 규칙들이 움직이는 표적이되고 게임은 생존자 이후의 모든 고화질 리얼리티 쇼의 기초를 구성 할 사회적인 상호 작용의 유형으로 변질됩니다. 왜, 규칙이 바뀌고 있고, 어떻게 / 왜 / 그들이 무엇을 나타 내기로되어 있는지에 대한 합의가없고, 더 중요한 것은 아무도 결정을 내리는 사람이 없다는 것입니다. 그 시점에서 모든 플레이어는 자신의 규칙과 혼란을 겪어서 두 명의 플레이어가 너무 피곤해서 뻔뻔 스러움을 유지하고 서서히 포기해야합니다.

따라서, 게임의 룰북이 정확하게 싱글 톤을 나타내면, 독점 룰북은 남용의 한 예가 될 것입니다.

이것이 프로그래밍에 어떻게 적용됩니까?

가변적 인 싱글 톤이 제시하는 확실한 스레드 안전성 및 동기화 문제를 제외하고 ... 여러 데이터 소스가 동시에 읽고 읽을 수있는 데이터 집합이 하나 있고 응용 프로그램 실행 수명 동안 존재할 경우, 아마 "지금 내가 올바른 유형의 데이터 구조를 사용하고 있는지 물어보십시오."라고 물어보십시오.

개인적으로 프로그래머가 응용 프로그램 내에서 트위스트 크로스 스레드 데이터베이스 저장소의 일종으로 싱글 톤을 악용하는 것을 보았습니다. 코드에서 직접 작업 해본 결과, (스레드 안전성을 높이기 위해 필요한 모든 스레드 잠금 때문에) 천천히 (동기화 버그의 예측할 수없는 / 간헐적 인 특성으로 인해) 작업 할 수있는 악몽과 '생산'조건 하에서 테스트하기가 거의 불가능합니다. 물론, 성능 문제의 일부를 극복하기 위해 폴링 / 시그널링을 사용하여 시스템을 개발할 수는 있지만 테스트를 통해 문제를 해결하지 못하고 '실제'데이터베이스가 훨씬 더 견고한 환경에서 동일한 기능을 수행 할 수있는 경우 왜 귀찮을까요? / 확장 방식.

싱글턴은싱글 톤이 제공하는 것을 필요로한다면 옵션. object의 write-one 읽기 전용 인스턴스입니다. 같은 규칙이 객체의 속성 / 멤버와도 연계되어야합니다.


  • 싱글 톤이 일부 데이터를 캐시한다면? - Yola
  • @Yola 싱글 톤이 미리 결정된 스케줄 및 / 또는 고정 된 스케줄로 업데이트되도록 스케줄 된 경우 쓰기 수를 줄여 스레드 경합을 줄입니다. 하지만 동일한 용도를 시뮬레이트하지 않는 단일 인스턴스를 모의하지 않는 한, 싱글 톤과 상호 작용하는 코드를 정확하게 테스트 할 수는 없습니다. TDD 사람들은 아마도 적합 할 것이지만 작동 할 것입니다. - Evan Plaice
  • @ EvanPlaice : 모의 경우에도 코드에 대한 몇 가지 문제가 있습니다.Singleton.getInstance(). 리플렉션을 지원하는 언어는 하나의 트루 인스턴스가 저장된 필드를 설정하여이를 해결할 수 있습니다. 하지만 IMO에서는 다른 클래스의 비공개 상태로 원숭이를 돌리고 나면 테스트가 다소 신뢰성이 떨어집니다. - cHao

21

싱글 톤은 단일 인스턴스가 아닙니다!

다른 답변 들과는 달리 나는 Singletons가 무엇이 잘못되었는지 이야기하고 싶지는 않습니다. 그러나 당신이 얼마나 강력하고 굉장한 지 보여주기 위해 그들은 올바르게 사용될 것입니다!

  • 문제: 싱글 톤은 멀티 스레딩 환경에서 어려움이 될 수 있습니다.

    해결책: 싱글 스레드 부트 스트랩 프로세스를 사용하여 싱글 톤의 모든 종속성을 초기화하십시오.
  • 문제: 싱글 톤을 모의하기가 어렵습니다.

    해결책: 방법 사용공장조롱을위한 패턴

    MyModel myModel = Factory.inject(MyModel.class); 지도를 만들 수 있습니다.MyModelTestMyModel클래스를 상속하는 클래스MyModel당신이 주사하게됩니다.TestMyModel간통죄.
  • 문제: 싱글 톤은 메모리 낭독을 일으킬 수 있습니다.

    해결책: 글쎄, 그들을 처분! 싱글 톤을 적절하게 처리하기 위해 앱에서 콜백을 구현하면, 연결된 모든 데이터를 제거하고 마침내 팩토리에서 데이터를 제거해야합니다.

내가 싱글 톤에 대해 말한 것처럼 싱글 톤은 하나의 인스턴스가 아닙니다.

  • 싱글 톤으로 가독성 향상: 당신은 자신의 수업을보고, 그것이 무엇이 종속성인지 알아 내기 위해 어떤 싱글 톤을 주입했는지 볼 수 있습니다.
  • 싱글 톤은 유지 보수를 향상시킵니다.: 일단 싱글 톤 주입을 삭제 한 클래스에서 의존성을 제거하면, 의존성을 옮긴 다른 클래스의 큰 링크를 편집 할 필요가 없습니다 (이것은 저에게 냄새 나는 코드입니다@ 짐 버거)
  • 싱글 톤은 메모리와 성능을 향상시킵니다.: 응용 프로그램에서 어떤 일이 발생하고 전달하기 위해 긴 콜백 체인이 필요하면 Singleton을 사용하여 중간 사람을 잘라내어 성능과 메모리 사용을 향상시킵니다 (불필요한 지역 변수를 피함). 할당).


  • 이것은 싱글 톤에 대한 나의 주요 문제를 다루지 않습니다. 싱글 톤은 프로젝트의 수천 개의 클래스 중 하나에서 글로벌 상태에 액세스 할 수 있도록합니다. - LegendLength
  • 그게 목적 일거야. - Ilya Gazman

21

Wikipedia Singleton_pattern을 참조하십시오.

그것은 또한 지나치게 사용되어 클래스의 유일한 인스턴스가 실제로 필요하지 않은 상황에서 불필요한 제한을 도입한다고 생각하는 사람들에 의해 반 패턴으로 간주됩니다. [1] [2] [3] [4]

참고 문헌 (해당 기사의 관련 참조 만)

  1. ^ 알렉스 밀러.#1 : 싱글 톤이 싫어하는 패턴, 2007 년 7 월
  2. ^ Scott Densmore.왜 싱글 톤이 악한가?, 2004 년 5 월
  3. ^ Steve Yegge.싱글 톤은 어리 석음으로 여겼다., 2004 년 9 월
  4. ^ J. 레인 즈 버거, IBM.싱글 톤을 현명하게 사용하십시오., 2001 년 7 월


  • 패턴에 대한 설명이 악으로 간주되는 이유를 설명하지 못했습니다 ... - Jrgns
  • 거의 공정하지 않음 : "너무 과도하다고 생각되는 일부 사람들은 반 패턴으로 간주되어 클래스의 유일한 인스턴스가 실제로 필요하지 않은 상황에서 불필요한 제한을 도입합니다." 참조를보세요 ... 어쨌든 저에게 RTFM이 있습니다. - GUI Junkie

20

싱글 톤이 나쁘다는 것에 대한 제 대답은 항상 "그들이 제대로하기가 어렵습니다"입니다. 언어의 기본 구성 요소 중 많은 부분은 컴퓨팅의 다른 측면 (로컬 호스트, 기본 경로, 가상 파일 시스템 등)의 구성 요소와 마찬가지로 싱글 톤 (클래스, 함수, 네임 스페이스 및 연산자)이며 우발적 인 것은 아닙니다. 그것들은 수시로 문제와 좌절을 일으키지 만, 많은 일들을 더 잘 수행 할 수 있습니다.

내가보기에 가장 큰 두 가지 원인은 다음과 같습니다. 글로벌 & 싱글 톤 폐쇄를 정의하지 못했습니다.

기본적으로 싱글 톤은 전역 변수로 이야기됩니다. 그러나 지구상의 모든 나쁜 점 (슬프게도, 전부는 아님)은 본질적으로 글로벌이 아니라, 어떻게 사용 하는가에 있습니다. Singletons도 마찬가지입니다. 실제로 "단일 인스턴스"가 "전 세계적으로 액세스 가능"하다는 것을 의미 할 필요는 없습니다. 그것은 더 자연스러운 부산물이며, 우리가 알고있는 모든 나쁜 점을 감안할 때, 글로벌 접근성을 개발하는 데 급히 서어서는 안됩니다. 프로그래머가 Singleton을 보게되면 인스턴스 메서드를 통해 직접 액세스하는 것처럼 보입니다. 대신 다른 객체처럼 탐색해야합니다. 대부분의 코드는 Singleton (loose coupling, right?)을 다루는 것을 인식하지 못합니다. 작은 코드 만 전역 객체처럼 객체에 액세스하면 많은 피해가 취소됩니다. 인스턴스 함수에 대한 액세스를 제한하여이를 적용하는 것이 좋습니다.

싱글 톤 컨텍스트도 매우 중요합니다. 싱글 톤의 특징을 정의하는 것은 "오직 하나"라는 것이지만, 진실은 일종의 컨텍스트 / 네임 스페이스 내에서 "유일한 것"이라는 것입니다. 그들은 일반적으로 스레드, 프로세스, IP 주소 또는 클러스터 당 하나이지만 프로세서, 기계, 언어 네임 스페이스 / 클래스 로더 / 무엇이든, 서브넷, 인터넷 등과 같이 하나씩이 될 수도 있습니다.

덜 일반적인 다른 실수는 싱글 톤 라이프 스타일을 무시하는 것입니다. 단지 하나만 존재하기 때문에 Singleton은 "항상 존재하고 항상 존재할 것입니다"라는 전능함을 의미하지 않으며, 일반적으로 바람직하지도 않습니다 (시작과 끝이없는 객체는 코드에서 모든 종류의 유용한 가정을 위반합니다. 상황이 가장 절실합니다.

이러한 실수를 피하면 싱글 톤은 여전히 PITA가 될 수 있습니다. 비트가 나올 때마다 최악의 문제가 크게 완화됩니다. Java Singleton은 클래스 로더 당 한 번 (스레드 안전성 정책이 필요함을 의미 함) 명시 적으로 정의되며 정의 된 작성 및 삭제 메소드 및 호출되는시기와 방법을 지정하는 라이프 사이클과 인스턴스 메소드가 가지고있는 라이프 사이클을 상상해보십시오. 패키지 보호이므로 일반적으로 다른 비 전역 객체를 통해 액세스됩니다. 여전히 문제의 잠재적 원천이지만, 확실히 적은 문제.

슬프게도, 싱글 톤을하는 법에 대한 좋은 예를 가르치는 것보다. 우리는 나쁜 예를 가르치고, 프로그래머들이 잠시 사용하지 못하게 한 다음 잘못된 디자인 패턴이라고 알려줍니다.


16

그것은 그 싱글 톤 자체가 나쁘지는 않지만 GoF 디자인 패턴입니다. 실제로 유효한 유일한 인수는 특히 테스트가 병렬로 실행되는 경우 GoF 디자인 패턴이 테스트와 관련이 없다는 것입니다.

코드에서 다음과 같은 방법을 적용하면 클래스의 단일 인스턴스를 사용할 수 있습니다.

  1. 싱글 톤으로 사용될 클래스가 인터페이스를 구현하는지 확인하십시오. 이를 통해 동일한 인터페이스를 사용하여 스텁 또는 모의 객체를 구현할 수 있습니다.

  2. 싱글 톤이 스레드로부터 안전한지 확인하십시오. 그것은 주어진 것입니다.

  3. 싱글 톤은 본질적으로 단순해야하며 지나치게 복잡하지 않아야합니다.

  4. 싱글 톤을 주어진 객체에 전달해야하는 응용 프로그램의 런타임 중에 해당 객체를 빌드하는 클래스 팩토리를 사용하고 클래스 팩토리가이를 필요로하는 클래스에 싱글 톤 인스턴스를 전달하게합니다.

  5. 테스트 중에 결정적인 동작을 보장하려면 실제 클래스 자체 또는 비헤이비어를 구현하는 스텁 / 모의 객체와 별도의 인스턴스로 싱글 톤 클래스를 만들고이를 필요로하는 클래스에 그대로 전달합니다. 테스트 도중 싱글 톤이 필요한 테스트 대상 객체를 만드는 클래스 요소를 사용하지 마십시오.이 요소는 단일 글로벌 인스턴스를 전달하므로 용도를 벗어납니다.

우리는 솔루션에서 싱글 톤을 사용하여 병렬 테스트 실행 스트림에서 결정 론적 동작을 테스트 할 수있는 많은 성공을 거두었습니다.


  • +1,마침내해결할 답변언제싱글 톤이 유효 할 수 있습니다. - Pacerier

15

빈스 휴스턴나에게 합리적으로 보이는 다음 기준이 있습니다.

싱글 톤은 다음의 세 가지 기준 모두가 만족되는 경우에만 고려되어야합니다 :

  • 단일 인스턴스의 소유권을 합리적으로 할당 할 수 없음
  • 게으른 초기화가 바람직합니다.
  • 달리 글로벌 액세스가 제공되지 않습니다.

단일 인스턴스의 소유권, 초기화 발생시기 및 방법, 전역 액세스가 문제가되지 않는다면 Singleton은 충분히 흥미롭지 않습니다.


14

나는 받아 들여진 응답에있는 4 개 점을 제시하고 싶으면, 누군가가 왜 나가 틀린 지 설명 할 수 있기를 바랍니다.

  1. 코드의 종속성을 왜 숨기고 있습니까? 이미 수십 개의 숨겨진 종속성 (C 런타임 호출, OS API 호출, 전역 함수 호출)이 있으며 단독 종속성을 쉽게 찾을 수 있습니다 (instance () 검색).

    "세계를 무언가로 바꾸는 것이 코드의 냄새입니다." 싱글 톤 코드 냄새를 피하기 위해 무언가를 지나치는 이유는 무엇입니까?

    싱글 톤을 피하기 위해 호출 스택에있는 10 개의 함수를 통해 객체를 전달하는 경우 그렇게 좋습니까?

  2. Single Responsibility Principle : 저는 이것이 다소 모호하며 당신의 책임 정의에 달려 있다고 생각합니다. 관련 질문은, 왜 이것을 추가하는 것일까?특유한수업 문제에 대한 "책임"?

  3. 클래스에 객체를 전달하면 왜 그 객체를 클래스 내에서 싱글 톤으로 사용하는 것보다 더 밀접하게 결합됩니까?

  4. 국가 기밀 유지 기간이 변경되는 이유는 무엇입니까? 싱글 톤은 수동으로 만들거나 파괴 할 수 있으므로 컨트롤이 그대로 유지되므로 수명이 비 싱글 톤 개체의 수명과 같게 만들 수 있습니다.

단위 테스트에 관하여 :

  • 모든 수업이 단위가되어야하는 것은 아닙니다. 테스트 한
  • 단위가되어야하는 모든 수업이 아닙니다. 테스트를 바꿀 필요가있다. 싱글 톤 구현
  • 만약 그들이해야 할 것단위 테스트가 필요하다. 구현을 변경해야하며, 수업을 쉽게 바꿀 수 있습니다. 싱글 톤을 사용하여 의존성을 통해 전달 된 싱글 톤 주입.


  • 1. 숨겨진 종속성은 모두?그것들도 나쁘다.숨겨진 의존성은 항상 악합니다. 그러나 CRT와 OS의 경우에는 이미 CRT와 OS가 있기 때문에 무엇인가를 얻을 수있는 유일한 방법입니다. (런타임이나 OS를 사용하지 않고 C 프로그램을 작성해보십시오.)이 작업을 수행하는 능력은 네거티브보다 훨씬 큽니다. 우리 코드의 싱글 톤은 그 사치품을 얻지 못한다; 관리 및 책임 분야에서 확고하게 자리 잡고 있기 때문에 모든 사용법 (추가 숨겨진 모든 종속성을 읽음)은 물건을 얻는 유일한 합리적인 방법으로 정당화되어야합니다. 대단히,대단히그들 중 몇몇은 실제로 있습니다. - cHao
  • 2. "책임" 일반적으로 "변경 이유"로 정의된다. 싱글 톤은 평생을 관리하고 실제 업무를 수행합니다. 작업 완료 방법을 변경하면또는객체 그래프가 어떻게 만들어 졌는지, 클래스를 변경해야합니다. 그러나 다른 코드에서 객체 그래프를 만들고 클래스가 실제 작업을 수행한다면 초기화 코드는 객체 그래프를 설정할 수 있습니다. 테스트 복식을 삽입하고 원하는대로 모든 것을 찢어 낼 수 있으므로 숨겨진 움직이는 부분에 더 이상 의존하지 않으므로 모든 것이 모듈화되고 테스트 가능합니다. - cHao
  • @ caHao : 1. "물건을 처리 할 수있는 능력이 네거티브보다 훨씬 크다"는 것을 잘 알고 있습니다. 예를 들어 로깅 프레임 워크가 있습니다. 개발자가 로깅을 꺼리는 경우 함수 호출 레이어를 통해 종속성 주입을 통해 글로벌 로깅 객체를 전달하도록하는 것이 바람직하지 않습니다. 따라서 싱글 톤. 3. 클래스의 클라이언트가 다형성을 통해 동작을 제어하도록하려는 경우 단단한 연결 지점 만 관련됩니다. 그런 경우는 많지 않습니다. - Jon
  • 4. " 수동으로 삭제할 수 없음 " "하나의 인스턴스 일 수 있음"의 논리적 의미이다. 싱글 톤을 어떻게 정의했는지, 같은 것을 말하는 것은 아닙니다. 모든 수업해서는 안된다.단위 테스트를 받아야한다. 이는 비즈니스 의사 결정이며 때로는 시장 출시 또는 개발 비용이 우선시됩니다. - Jon
  • 3. 다형성을 원하지 않으면 인스턴스가 필요하지 않습니다. 어쨌든 하나의 객체와 하나의 구현체에 자신을 묶는 정적 클래스로 만들 수도 있습니다. 그리고 최소한 API는 당신만큼 거짓말하지 않습니다. - cHao

13

나는 선과 악의 논쟁에 대해 논평하지 않을 것이지만, 나는 그것들을 사용하지 않았다.따라왔다. 사용의존성 주입거의 싱글 톤, servicelocators 및 공장에 대한 내 요구 사항을 제거했습니다. 필자는이 작업이 최소한 작업의 유형 (Java 기반 웹 응용 프로그램)에있어 훨씬 더 생산적이고 깨끗한 환경이라는 것을 알았습니다.


  • Spring Bean은 기본적으로 싱글 톤이 아닙니까? - slim
  • 그래,하지만 코딩은 ' 싱글 톤. 싱글 톤을 쓰지 않고 ' (즉, 디자인 패턴에 따라 개인 생성자 인 yada yada yada를 사용하여) - 그렇지만 봄에는 단일 인스턴스를 사용하고 있습니다. - prule
  • 그래서 다른 사람들이 그것을 할 때 Ok (만약 내가 그것을 사용한다면),하지만 다른 사람들이 그것을 사용하고 그것을 사용하지 않는다면 그것은 악합니다. - Dainius

12

싱글 톤은 순수주의의 관점에서 나쁘다.

우화적인 관점에서 볼 때,싱글 톤은 트레이드 오프 개발 시간 대 복잡성이다..

귀하의 신청서가 그만큼 변경되지 않을 것이라는 것을 알고 있다면 그들은 함께 갈 수 있습니다. 예상치 못한 방식으로 요구 사항이 변경되는 경우 리팩터링해야 할 수도 있음을 알고 있습니다 (대부분의 경우 매우 좋습니다).

싱글 톤은 때로는 또한 복잡합니다.단위 테스트.


  • 내 경험은출발싱글 톤을 사용하면 장기적으로 계산하지 않고 단기적으로도 실제로 당신을 해칠 수 있습니다. 이 효과는 응용 프로그램이 이미 일정 시간 동안 이미 존재하고 다른 싱글 톤으로 이미 감염된 경우에는 덜 효과적입니다. 처음부터 시작 하시겠습니까? 어떤 희생을 치르더라도 피하십시오! 객체의 단일 인스턴스를 원하십니까? 팩토리가이 객체의 인스턴스를 관리하게합니다. - Sven
  • AFAIK 싱글 톤~이다.팩토리 메소드. 따라서 추천을 얻지 못합니다. - tacone
  • "A 공장" ! = "" 동일한 클래스의 다른 유용한 항목과 분리 할 수없는 factory_method " - Sven

11

패턴이 본질적으로 잘못 설정된 것은 없습니다. 모델의 일부 측면에 실제로 사용되고 있다고 가정하면 패턴에 아무런 문제가 없습니다.

반발은 과용에 기인한다고 생각합니다. 과용은 이해와 구현이 가장 쉬운 패턴이라는 사실 때문입니다.


  • 백라시즘은 그들이 처한 악몽이라는 것을 깨닫고 형식화 된 단위 테스트를 연습하는 사람들과 더 관련이 있다고 생각합니다. - Jim Burger
  • 이것이 -1에있는 이유를 모르겠습니다. 가장 설득력있는 대답은 아니지만 잘못하지 않았습니다. - Outlaw Programmer

11

싱글 톤은 패턴이며 다른 도구와 마찬가지로 사용하거나 악용 될 수 있습니다.

싱글 톤의 나쁜 부분은 일반적으로 사용자입니다 (또는 싱글 톤을 부적절하게 사용하도록 설계되지 않은 것에 대해서는이를 사용해야합니다). 가장 큰 범죄자는 가짜 글로벌 변수로 싱글 톤을 사용하고 있습니다.


  • 고마워 로키 :) 정확히 내 요점. 전체 마녀 사냥은 저에게 goto 토론을 생각 나게합니다. 도구는 사용법을 알고있는 사람들을위한 도구입니다. 당신이 좋아하지 않는 도구를 사용하는 것은 위험 할 수 있으므로 피하십시오. 그러나 다른 사람들에게 도구 사용을 배제하지 말라고하십시오. 나는 정확히 "pro-singleton"이 아니다. 그러나 나는 그런 도구를 가지고 있고 그것을 사용하는 것이 적절한 곳에서 느낄 수 있다는 사실을 좋아합니다. 기간. - dkellner

8

로거 또는 데이터베이스 연결과 같은 싱글 톤을 사용하여 코드를 작성한 후 둘 이상의 로그 또는 하나 이상의 데이터베이스가 필요하다는 것을 알게되면 문제가 발생합니다.

싱글 톤은 정규 객체로 이동하기가 매우 어렵습니다.

또한 스레드 안전하지 않은 싱글 톤을 작성하는 것은 너무 쉽습니다.

싱글 톤을 사용하는 것보다 필요한 모든 유틸리티 객체를 함수에서 함수로 전달해야합니다. 이 모든 것을 도우미 객체로 래핑하면 다음과 같이 간단해질 수 있습니다.

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}


  • 각 메소드에 대한 인수를 넘기는 것은 훌륭합니다. API를 오염시키는 방법을 적어도 10 가지 방법으로 찾아야합니다. - Dainius
  • 이것은 분명히 단점이며, 중첩 된 호출로 전파되는 인수를 통해 언어에 의해 처리되어야하지만, 지원이 없으면 수동으로 수행해야합니다. 시스템 클럭을 나타내는 객체와 같은 자연스러운 싱글 톤조차도 문제가 발생할 가능성이 있음을 고려하십시오. 예를 들어, 시계 관련 코드 (다중 요금 전기 미터라고 생각하십시오)를 테스트로 어떻게 다룰 예정입니까? - Roman Odaisky
  • 싱글 톤을 테스트하지 않으면 왜 행동하는지, 2 개의 원격 객체가 서로 다른 행동에 의존하면 싱글 톤 문제가 아닌지, 테스트하는 대상에 따라 달라집니다. - Dainius
  • 중첩 호출로 전파 할 언어를 제공 할 수 있습니까? - Dainius
  • 하나의 모듈이 다른 모듈에 종속되어 있고 그것을 모르거나 모를 수 없다면, 그 모듈이 싱글 톤인지 여부와 관계없이 하드가됩니다. 사람들은 상속을 자주 사용하지만 컴포지션을 사용해야하는 곳이 많습니다.하지만 많은 사람들이 설계 실수를 저지르고 있기 때문에 상속을 피하고 OOP를 피해야합니다. 그렇지 않습니까? - Dainius

7

싱글 톤 문제는 범위가 확대되는 문제이므로연결. 단일 인스턴스에 대한 액세스가 필요하고 다른 방법으로 수행 될 수있는 상황이 있음을 부인할 수 없습니다.

나는 이제 주변을 디자인하는 것을 선호한다.제어 반전(IoC) 용기에 넣고 수명이 용기에 의해 제어되도록합니다. 이렇게하면 단일 인스턴스가 있다는 사실을 알지 못하도록 인스턴스에 의존하는 클래스의 이점을 얻을 수 있습니다. 싱글 톤의 수명은 앞으로 변경 될 수 있습니다. 최근에 그런 예가 발생하면 단일 스레드에서 다중 스레드로 쉽게 조정할 수 있습니다.

FWIW, PIA의 경우 단위 테스트를 시도하면 PIA로 디버깅, 버그 수정 또는 향상을 시도합니다.


7

Chris Reath의이 주제에 관한 최근 기사주석이없는 코딩.

참고 : 주석없는 코딩은 더 이상 유효하지 않습니다. 그러나 링크 된 문서가 다른 사용자에 의해 복제되었습니다.

http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx


6

아무도 아직 말하지 않은 싱글 톤에 대해 한 가지 더 있습니다.

대부분의 경우 "싱글 톤"은 인터페이스의 특성보다는 일부 클래스의 구현 세부 사항입니다. Inversion of Control Container는이 특성을 클래스 사용자로부터 숨길 수 있습니다. 클래스를 싱글 톤으로 표시하면됩니다 (@Singleton예를 들어 자바의 주석) 그게 다예요. IoCC는 나머지를 할 것입니다. 액세스가 이미 IoCC에 의해 관리되기 때문에 싱글 톤 인스턴스에 대한 전역 액세스를 제공 할 필요가 없습니다. 따라서 IoC 싱글 톤에는 아무런 문제가 없습니다.

GoF 싱글 톤은 IoC와 반대입니다. 싱글 톤은 getInstance () 메서드를 통해 인터페이스에서 "싱글 톤"을 노출해야하므로 위의 모든 것에서 고통받습니다.


  • 내 의견으로는, "독신 성" 런타임 환경의 세부 사항이며 클래스 코드를 작성한 프로그래머는 고려하지 않아야합니다. 오히려 그것은 클래스 USER에 의해 만들어지는 고려 사항입니다. USER 만 실제로 필요한 인스턴스의 수를 압니다. - Earth Engine

6

싱글 톤은 나쁘지 않습니다. 세계적으로 유일하지 않은 세계적으로 고유 한 것을 만들 때만 안 좋은 일입니다.

그러나 "응용 프로그램 범위 서비스"(구성 요소가 상호 작용하는 메시징 시스템에 대해 생각해보십시오.) -이 단일 호출에 대한 CALLS, "SendMessage (...)"메서드가있는 "MessageQueue"클래스.

그 다음 장소에서 다음을 수행 할 수 있습니다.

MessageQueue.Current.SendMessage (새 MailArrivedMessage (...));

물론, 다음과 같이하십시오.

MessageQueue.Current.RegisterReceiver (this);

IMessageReceiver를 구현하는 클래스


  • 범위가 작은 두 번째 메시지 큐를 만들려면 왜 코드를 다시 작성하여 코드를 만들지 않아야합니까? 싱글 톤은 그것을 방지합니다. 그러나 방금 일반 메시지 대기열 클래스를 만든 다음 " 애플리케이션 범위 " 역할을하는 하나의 전역 인스턴스를 만든 경우 하나, 다른 용도로 두 번째 인스턴스를 만들 수 있습니다. 하지만 클래스를 싱글 톤으로 만들면둘째메세지 큐 클래스. - jalf
  • 또한 MessageQueue와 같이 어디에서나 멋지게 호출 할 수 있도록 글로벌 CustomerOrderList를 보유해야하는 이유는 무엇입니까? 나는 그 대답이 둘 다 동일하다고 믿는다 : 그것은 효과적으로 전역 변수를 만든다. - LegendLength

6

너무 많은 사람들이 쓰레드 안전하지 않은 객체를 싱글 톤 패턴으로 넣는다. DataContext의 예를 보았습니다 (LINQ     SQL)은 싱글 톤 패턴으로 처리되었지만 DataContext는 스레드로부터 안전하지 않으며 순전히 작업 단위 개체이기도합니다.


  • 많은 사람들이 안전하지 않은 멀티 쓰레 디드 코드를 작성합니다. 그러면 쓰레드를 제거해야합니까? - Dainius
  • @Dainius : 사실, 네. IMO 기본 동시성 모델은 두 프로세스가 (1) 서로 쉽게 메시지를 전달하고 / 또는 (2) 필요에 따라 메모리를 공유 할 수있는 방법으로 다중 프로세스 여야합니다. 스레딩은 공유하려는 경우 유용합니다.모두, 그러나 당신은 결코 그것을 정말로 원하지 않습니다. 전체 주소 공간을 공유하여 에뮬레이트 될 수 있지만 안티 패턴으로 간주됩니다. - cHao
  • @Dainius : 물론 솔직하고 선한 동시성이 필요하다고 가정합니다. OS가 다른 일을하기를 기다리는 동안 원하는 것은 종종 하나의 일을 할 수 있어야한다는 것입니다. 예를 들어, 소켓에서 읽는 동안 UI 업데이트. 괜찮은 비동기 API를 사용하면 대다수의 경우에 풀 스레딩이 필요하지 않게 될 수 있습니다. - cHao
  • 그래서 거대한 데이터 매트릭스를 가지고 있다면, 프로세스가 필요합니다. 많은 사람들이 그렇게 잘못했을 수 있기 때문에, 단일 스레드에서 그렇게하는 것이 낫습니다. - Dainius
  • @Dainius : 많은 경우, 그렇습니다. (스레딩은 실제로천천히믹스에 동기화를 추가하면됩니다. 이것은 멀티 스레딩이 대부분의 사람들이 처음 생각해야하는 이유의 대표적인 예입니다.) 다른 경우에는 필요한 것만을 공유하는 두 개의 프로세스를 갖는 것이 낫습니다. 물론 메모리를 공유하는 프로세스를 준비해야합니다. 솔직히 말해서 나는 그것을좋은적어도 공유는 모든 것을 공유하는 것보다 훨씬 낫습니다. 명시 적으로 (그리고 이상적으로 알기 위해) 어떤 부분이 공유되어야하는지, 따라서 어떤 부분이 스레드로부터 안전해야 하는지를 요구해야합니다. - cHao

4

그것들은 기본적으로 객체 지향적 인 전역 변수이기 때문에 필요하지 않게 클래스를 디자인 할 수 있습니다.


  • 클래스를 한 번 인스턴스로 제한하지 않으면 클래스에서 정적 멤버가 세마포로 관리되어야합니다.이 멤버는 거의 동일한 것으로 나타납니다. 대안은 무엇입니까? - Jeach
  • " MainScreen "이라는 거대한 응용 프로그램이 있습니다. 이 화면은 많은 더 작은 모달 / 모달이 아닌 윈도우 / UI 양식을 엽니 다. IMHO MainScreen이 싱글 톤이어야한다고 생각합니다. 예를 들어, 응용 프로그램의 맨 구석에있는 위젯이 MainScreen의 상태 표시 줄에 상태를 나타내려고하면 MainScreen.getInstance ( ) .setStatus ( "Some Text"); 대안으로 무엇을 제안합니까? MainScreen을 응용 프로그램 전체에 전달 하시겠습니까 ?? :디 - Salvin Francis
  • @SalvinFrancis : 내가 추천할만한 것은, 당신이 신경 쓰면 안되는 물건에 관심을 가지면서 앱을 가로 질러 몰래 들어가서 서로 어울리는 물건을 가지고 있지 않다는 것입니다. :) 당신의 모범은 사건으로 훨씬 잘 끝날 것입니다. 이벤트를 올바로 수행하면 위젯이 MainScreen을 전혀 신경 쓸 필요조차 없습니다. 그냥 "안녕하세요, 일어난 일"을 브로드 캐스트합니다.도대체 무엇이"일어난 물건들"에 가입했다. 이벤트 (MainScreen, WidgetTest 또는 완전히 다른 것일 수 있습니다!)가 응답 방법을 결정합니다. 이것이 OOP가가정의어쨌든 끝내야한다. :) - cHao
  • @ Salvin 디버깅 할 때 MainScreen에 대한 판단이 얼마나 어려운지 고려해보십시오. 많은 구성 요소에 의해 업데이트되었습니다. 당신의 예는 싱글 톤이 왜 나쁜지에 대한 완벽한 이유입니다. - LegendLength

4

여러 사람 (또는 팀)이 유사하거나 동일한 솔루션에 도달하면 패턴이 나타납니다. 많은 사람들이 여전히 원래 형태로 또는 팩토리 템플릿을 사용하여 싱글 톤을 사용합니다 (Alexandrescu의 Modern C ++ Design에서 좋은 토론). 객체의 수명을 관리하는 데있어 동시성과 난이도가 주요 장애물이며, 이전과 마찬가지로 쉽게 관리 할 수 있습니다.

모든 선택과 마찬가지로, 싱글 톤은 기복의 공정한 분배를 가지고 있습니다. 나는 그들이 적당히 사용할 수 있다고 생각합니다. 특히 응용 프로그램 수명에서 살아남은 객체의 경우에 특히 그렇습니다. 그들이 닮은 (그리고 아마도 그럴듯한) 사실은 아마도 순수 주의자들을 출발 시켰을 것이다.


4

첫째, 수업 및 그 공동 작업자는 먼저 착수 자에 초점을 맞추기보다는 의도 된 목적을 수행해야합니다. 수명주기 관리 (인스턴스가 범위를 벗어날 때 인스턴스가 만들어지면)는 클래드 책임의 일부가되어서는 안됩니다. 이를위한 가장 좋은 방법은 종속성 주입을 사용하여 종속성을 관리하기위한 새로운 구성 요소를 만들거나 구성하는 것입니다.

종종 소프트웨어는 더 복잡해지면서 서로 다른 상태의 "싱글 톤"클래스의 여러 독립 인스턴스를 갖는 것이 합리적입니다. 이런 경우에는 싱글 톤을 잡기위한 코드를 작성하는 것이 잘못되었습니다. 작은 단순한 시스템에서는 Singleton.getInstance ()를 사용하는 것이 좋지만 동일한 클래스의 다른 인스턴스가 필요한 경우에는 작동하지 않습니다.

어떤 클래스도 싱글 톤으로 생각해서는 안되며, 오히려 그것의 사용법이나 의존성을 구성하는 데 어떻게 사용되어야 하는지를 설명해야합니다. 빠르고 간단하게 말하자면 이것은 중요하지 않습니다. 단지 코딩 만하면 파일 경로가 중요하지 않다고 말하면서 더 큰 애플리케이션의 경우 DI를 사용하여 그러한 종속성을 계산하고보다 적절한 방법으로 관리해야합니다.

테스트에서 싱글 톤이 발생시키는 문제는 하드 코딩 된 단일 사용 사례 / 환경의 증상입니다. 테스트 스위트와 많은 테스트는 각각 개별적이며 싱글 톤의 하드 코딩과 호환되지 않는 별도의 테스트입니다.

연결된 질문


관련된 질문

최근 질문