영광스러운 글로벌 변수-영광스러운 글로벌 클래스가됩니다. 어떤 사람들은 객체 지향 디자인을 깨뜨린다고 말합니다.
싱글 톤을 사용하는 것이 좋은 오래된 로거 이외의 시나리오를 알려주십시오.
영광스러운 글로벌 변수-영광스러운 글로벌 클래스가됩니다. 어떤 사람들은 객체 지향 디자인을 깨뜨린다고 말합니다.
싱글 톤을 사용하는 것이 좋은 오래된 로거 이외의 시나리오를 알려주십시오.
답변:
진실에 대한 나의 탐구에서 나는 싱글 톤을 사용해야하는 "허용 가능한"이유가 거의 없다는 것을 발견했다.
인터넷에서 반복해서 나타나는 경향이있는 한 가지 이유는 "로깅"클래스 때문입니다. 이 경우 로깅 클래스는 일반적으로 프로젝트의 모든 클래스에 의해 구역이 반복해서 사용해야하므로 클래스의 단일 인스턴스 대신 싱글 톤을 사용할 수 있습니다. 모든 클래스가이 로깅 클래스를 사용하면 종속성 주입이 번거로워집니다.
로깅은 코드의 실행에 영향을 미치지 않기 때문에 "허용 가능한"싱글 톤의 특정 예입니다. 로깅을 비활성화하면 코드 실행이 동일하게 유지됩니다. 동일하게 사용하십시오. Misko는 다음과 같은 방식 으로 Singletons의 근본 원인에 다음과 같이 설명합니다 . "여기의 정보는 한 방향으로 흐릅니다. 애플리케이션에서 로거로. 로거는 전역 상태이지만 로거에서 애플리케이션으로 정보가 흐르지 않기 때문에 로거가 허용됩니다."
다른 유효한 이유도 있다고 확신합니다. " Patterns I Hate "의 Alex Miller 는 서비스 로케이터와 클라이언트 측 UI에 대한 "허용 가능한"선택에 대해 이야기합니다.
싱글턴 후보는 세 가지 요구 사항을 충족해야합니다.
제안 된 Singleton에 이러한 요구 사항 중 하나 또는 둘만있는 경우 재 설계는 거의 항상 올바른 옵션입니다.
예를 들어, 프린터 스풀러가 두 곳 이상에서 인쇄되지 않을 경우 (인쇄 메뉴) 뮤텍스를 사용하여 동시 액세스 문제를 해결할 수 있습니다.
간단한 로거는 아마도 유효한 싱글 톤의 가장 명백한 예이지만 더 복잡한 로깅 체계로 변경 될 수 있습니다.
시작시에만 읽어야 할 구성 파일을 읽고 싱글 톤으로 캡슐화합니다.
Properties.Settings.Default
.NET과 유사합니다 .
공유 리소스를 관리해야 할 때 싱글 톤을 사용합니다. 예를 들어 프린터 스풀러. 동일한 자원에 대한 요청이 충돌하지 않도록하려면 애플리케이션에 스풀러 인스턴스가 하나만 있어야합니다.
또는 데이터베이스 연결 또는 파일 관리자 등
일부 전역 상태 (사용자 언어, 도움말 파일 경로, 응용 프로그램 경로)를 저장하는 싱글 톤 만 읽을 수 있습니다. 비즈니스 로직을 제어하기 위해 싱글 톤을 사용하는 것에주의하십시오-싱글은 거의 항상 여러 개가됩니다
데이터베이스에 대한 연결 (또는 연결 풀) 관리
또한 외부 구성 파일에서 정보를 검색하고 저장하는 데 사용합니다.
싱글 톤을 사용하는 방법 중 하나는 리소스에 대한 액세스를 제어하는 단일 "브로커"가 있어야하는 인스턴스를 다루는 것입니다. 싱글 톤은 로거에 적합합니다. 예를 들어 파일에 대한 액세스를 중개하여 독점적으로 만 쓸 수 있기 때문입니다. 로깅과 같은 경우에는 로그 파일과 같은 쓰기를 추상화하는 방법을 제공합니다. 캐싱 메커니즘을 싱글 톤 등으로 래핑 할 수 있습니다.
또한 창 / 스레드 등이 많은 응용 프로그램이 있지만 단일 통신 지점이 필요한 상황을 생각해보십시오. 한 번은 하나를 사용하여 응용 프로그램을 시작하려는 작업을 제어했습니다. 싱글 톤은 작업을 직렬화하고 관심있는 프로그램의 다른 부분에 상태를 표시하는 역할을 담당했습니다. 이런 종류의 시나리오에서는 싱글 톤을 응용 프로그램 내에서 실행되는 "서버"클래스와 같은 것으로 볼 수 있습니다 ... HTH
전체 응용 프로그램이 공유하는 리소스에 대한 액세스를 관리 할 때는 싱글 톤을 사용해야하며, 같은 클래스의 여러 인스턴스가있을 가능성이 있습니다. 공유 리소스 스레드에 안전하게 액세스하는 것이 이러한 종류의 패턴이 필수적인 경우의 좋은 예입니다.
싱글 톤을 사용할 때 실수로 종속성을 숨기지 않아야합니다. 이상적으로는 싱글 톤 (응용 프로그램의 대부분의 정적 변수와 같이)은 응용 프로그램의 초기화 코드 실행 중 설정되고 (C # 실행 파일의 경우 정적 void Main (), Java 실행 파일의 경우 정적 void main ()) 전달됩니다. 인스턴스화되어 필요한 다른 모든 클래스. 이것은 테스트 가능성을 유지하는 데 도움이됩니다.
싱글 톤의 실제 예는 Test :: Builder 에서 찾을 수 있습니다. Test :: Builder 는 거의 모든 최신 Perl 테스트 모듈을 지원합니다. Test :: Builder singleton은 테스트 프로세스의 상태 및 히스토리 (기록 테스트 결과, 실행 횟수 테스트)와 테스트 출력이 진행되는 위치 등을 저장하고 중개합니다. 이것들은 모두 하나의 테스트 스크립트에서 함께 작동하기 위해 다른 작성자가 작성한 여러 테스트 모듈을 조정하는 데 필요합니다.
Test :: Builder의 싱글 톤의 역사는 교육적입니다. 전화하면 new()
항상 같은 물건이됩니다. 첫째, 모든 데이터는 객체 자체에 아무것도없는 클래스 변수로 저장되었습니다. 이것은 Test :: Builder 자체를 테스트하고 싶을 때까지 작동했습니다. 그런 다음 두 가지 Test :: Builder 객체, 하나는 더미로 설정하여 동작 및 출력을 캡처하고 테스트하고 다른 하나는 실제 테스트 객체가 필요했습니다. 그 시점에서 Test :: Builder는 실제 객체로 리팩토링되었습니다. 싱글 톤 객체는 클래스 데이터로 저장되어 new()
항상 반환합니다. create()
새로운 객체를 만들고 테스트를 가능하게하기 위해 추가되었습니다.
현재 사용자는 자체 모듈에서 Test :: Builder의 일부 동작을 변경하려고하지만 다른 테스트 결과는 그대로두고 테스트 히스토리는 모든 테스트 모듈에서 공통으로 유지됩니다. 현재 일어나고있는 것은 모 놀리 식 Test :: Builder 객체가 Test :: Builder 인스턴스를 모아서 더 작은 조각 (이력, 출력, 형식 ...)으로 나누는 것입니다. 이제 Test :: Builder가 더 이상 싱글 톤일 필요는 없습니다. 히스토리와 같은 구성 요소도 가능합니다. 이것은 싱글 톤의 융통성없는 필요성을 한 단계 낮춘다. 사용자가 조각을 혼합하고 일치시킬 수있는 유연성을 제공합니다. 작은 싱글 톤 객체는 이제 데이터를 저장할 수 있으며 포함 된 객체는 사용 방법을 결정합니다. Test :: Builder 히스토리 및 출력 싱글 톤을 사용하여 Test :: Builder가 아닌 클래스를 재생할 수도 있습니다.
데이터 조정과 행동의 유연성 사이에 밀고 당기는 것처럼 보입니다. 데이터 무결성을 보장하기 위해 가능한 한 가장 적은 양의 행동으로 공유 데이터 주위에 싱글 톤을 배치함으로써 완화 할 수 있습니다.
데이터베이스 또는 파일에서 구성 특성 오브젝트를로드 할 때 단일 특성으로 사용하는 것이 좋습니다. 서버가 실행되는 동안 변경되지 않는 정적 데이터를 계속 다시 읽을 이유가 없습니다.
상태 패턴을 구현할 때 (GoF 책에 표시된 방식으로) 싱글 톤을 사용할 수 있습니다. 구체적인 State 클래스에는 자체 상태가 없으며 컨텍스트 클래스 측면에서 작업을 수행하기 때문입니다.
Abstract Factory를 싱글 톤으로 만들 수도 있습니다.
setState()
상태 생성 정책 결정에 책임을 져야합니다. 프로그래밍 언어가 템플릿 또는 제네릭을 지원하면 도움이됩니다. Singleton 대신, Monostate 패턴을 사용하여 상태 객체를 인스턴스화하면 동일한 전역 / 정적 상태 객체를 재사용하게됩니다. 인스턴스화 된 상태가 단일 상태임을 사용자가 알 필요가 없으므로 상태 변경 구문은 변경되지 않은 상태로 유지 될 수 있습니다.
공유 자원. 특히 PHP에서는 데이터베이스 클래스, 템플릿 클래스 및 전역 변수 저장소 클래스가 있습니다. 코드 전체에서 사용되는 모든 모듈 / 클래스에서 모두 공유해야합니다.
실제 객체 사용법입니다-> 템플릿 클래스에는 작성중인 페이지 템플릿이 포함되어 있으며 페이지 출력에 추가하는 모듈에 의해 모양이 추가되고 변경됩니다. 이러한 상황이 발생할 수 있도록 단일 인스턴스로 유지해야하며 데이터베이스에서도 마찬가지입니다. 공유 데이터베이스 싱글 톤을 사용하면 모든 모듈 클래스가 쿼리에 액세스하여 다시 실행할 필요없이 액세스 할 수 있습니다.
글로벌 변수 저장소 싱글 톤은 글로벌하고 안정적이며 쉽게 사용할 수있는 변수 저장소를 제공합니다. 코드를 크게 정리합니다. 다음과 같이 단일 구성으로 배열의 모든 구성 값이 있다고 가정하십시오.
$gb->config['hostname']
또는 다음과 같은 배열의 모든 언어 값을 갖습니다.
$gb->lang['ENTER_USER']
페이지의 코드를 실행하면 이제 성숙해집니다.
$template
Singleton, $gb
교체 할 lang 배열이 있는 싱글 톤이며 모든 출력이로드되어 준비됩니다. 이제 성숙 템플릿 개체의 페이지 값에있는 키로 키를 교체 한 다음 사용자에게 제공하면됩니다.
이것의 가장 큰 장점은 무엇이든 원하는 후 처리를 할 수 있다는 것입니다. 모든 언어 값을 Google 번역 또는 다른 번역 서비스로 파이프하여 다시 가져 와서 번역 할 수 있습니다 (예 : 번역 된 위치). 또는 원하는대로 페이지 구조 나 컨텐츠 문자열을 바꿀 수 있습니다.
플러그 가능한 모듈을 다룰 때 명령 줄 매개 변수를 캡슐화하는 객체에 사용합니다. 메인 프로그램은로드 된 모듈에 대한 명령 줄 매개 변수가 무엇인지 알지 못하며 어떤 모듈이로드되는지 항상 알지 못합니다. 예를 들어, 매개 변수 자체가 필요하지 않은 메인로드 A (따라서 추가 포인터 / 참조가 필요한 이유는 확실하지 않습니다-오염처럼 보입니다), 모듈 X, Y 및 Z를로드합니다. 이 중 X와 Z는 매개 변수가 필요하거나 수락하므로 명령 줄 단일 항목으로 다시 호출하여 허용 할 매개 변수를 알려주고 런타임에 사용자가 실제로 지정했는지 확인하기 위해 호출합니다. 그들의.
여러 가지 방법으로 쿼리 당 하나의 프로세스 만 사용하는 경우 CGI 매개 변수를 처리하기위한 싱글 톤도 비슷하게 작동합니다 (다른 mod_ * 메소드는이 작업을 수행하지 않으므로 여기서는 좋지 않습니다. t mod_perl 또는 다른 세계로 포팅하는 경우 mod_cgi 세계에서 싱글 톤을 사용하십시오.
아마도 코드가있는 예입니다.
여기서 ConcreteRegistry는 포커 게임에서 싱글 톤으로 패키지 트리의 모든 동작이 게임의 몇 가지 핵심 인터페이스 (예 : 모델, 뷰, 컨트롤러, 환경 등의 외관)에 액세스 할 수 있도록합니다.
http://www.edmundkirwan.com/servlet/fractal/cs1/frac-cs40.html
에드
1-첫 번째 답변에 대한 의견 :
정적 로거 클래스에 동의하지 않습니다. 이는 구현에는 실용적이지만 단위 테스트에서는 대체 할 수 없습니다. 정적 클래스는 테스트 이중으로 대체 될 수 없습니다. 단위 테스트를하지 않으면 여기에 문제가 표시되지 않습니다.
2-손으로 싱글 톤을 만들지 않습니다. 공동 작업자를 객체에 주입 할 수있는 생성자를 사용하여 간단한 객체를 만듭니다. 싱글 톤이 필요한 경우 종속성 차단 프레임 워크 (Spring.NET, Unity for .NET, Spring for Java) 또는 기타를 사용합니다.
ILogger logger = Logger.SingleInstance();
들어이 메소드는 정적이며 ILogger의 정적으로 저장된 인스턴스를 리턴합니다. "종속성 주입 프레임 워크"의 예를 사용했습니다. 거의 모든 DI 컨테이너는 싱글 톤입니다. 이들의 구성은 정적으로 정의되며 궁극적으로 단일 서비스 공급자 인터페이스에서 액세스 / 저장됩니다.