2009-02-03 3 views
4

싱글 톤 패턴이나 정적 클래스 (즉 거의 정적 멤버 만 가진 클래스)의 구현을 발견 할 때마다 이것이 실제로 해킹이 아니며 따라서 클래스 및 인스턴스의 원칙을 심각하게 남용하지 않는지 궁금합니다. 클래스를 설계하고 단일 인스턴스를 생성하는 대신 단일 객체를 설계 할 수 있습니다. 나에게 클래스의 정적 멤버는 일반적으로 클래스에 어떤 종류의 특성을 추가하려고 시도합니다. 실제로는 클래스에 특성을 추가하려고합니다.정적 멤버가 클래스에 (글로벌) 객체를 일종의 클래스로 지정하지 않습니까?

하지만 단일 개체를 이와 같이 구현하는 것이 바람직합니까? 아니면 완전히 다른 방식으로 사물을 보았습니까? 그런 정적 클래스 나 싱글 톤이 실제 객체와 공통점이 있다고 생각하지 않습니까?

답변

1

단일 구성 파일이있는 응용 프로그램이 있습니다. 내 언어가 클래스 외부의 전역 함수 (예 : Java 또는 C#)를 지원하지 않으면 "싱글 톤"을 사용하지 않고 해당 파일에서 작동하는 함수를 어떻게 만들 수 있습니까?

싱글 톤 클래스를 구현하는 유일한 방법은 나에게만있는 것처럼 보입니다. 싱글 톤 패턴을 사용하면 객체에 포인터를 전달할 필요가 없습니다. 정적 메서드를 사용하여 다시 가져올 수 있기 때문입니다.

이것이 어떻게 모든 OO 원칙을 위반하는지는 알 수 없습니다. 구성 방법을 다루지 않는 다른 클래스 (예 : "유틸리티"클래스)에 구성 기능을 넣는 것과 같이 다른 방법으로 수행하려면 이 더 많으며 OO 원칙을 위반하는입니다.

+1

그러나 읽기 쉽고 유지하기 쉬운 코드를 얻기 위해 포인터를 전달하는 것이 더 좋지 않습니까? 사실 글로벌 변수와 다른 문제는 아직 다르게 포장되어 있습니다. 또한 http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/ – balu

+1

을보십시오 이론에서는, 확실하십시오. 그러나이 기사의 예제에서도 "CreditCard"클래스 생성자를 6 명의 멤버로 분해했으며 이는 단순한 예일뿐입니다. 이데올로기에 충실하기 위해 10 개 이상의 매개 변수가있는 기능을 갖는 것은 좋은 생각이 아닙니다. – SoapBox

+0

생성자를 통해 모든 종속성을 전달하는 것은 종속성 삽입을 수행하는 한 가지 방법 일뿐입니다. 또 다른 방법은 속성을 설정하는 것입니다. 또 다른 대안은 "서비스 탐지기"패턴입니다. 고전적인 기사 : http://www.martinfowler.com/articles/injection.html –

7

정적 멤버는 사실 전역에 대한 네임 스페이스 일뿐입니다. 그게 잘못이 아니야. 네임 스페이스가 좋으며 전역 작업이 일부 작업을 수행하는 가장 깨끗한 방법입니다.

싱글 톤은 다소 흥미로운 것일 수 있지만 비슷한 구조입니다 (예, 정적 멤버를 컴파일러가 관리하는 익명의 싱글 톤으로 생각할 수 있습니다).

대부분의 것들과 마찬가지로,이 도구들은 그들의 위치를 ​​가지고 있으며, 이데올로그들은 오직 특정한 이데올로기에 "적합"하는지에 대해 걱정합니다.

2

언어에 따라 클래스는 개체입니다. 루비와 자바에서는 클래스 클래스입니다. 파이썬에서는 기억이 안납니다 (타입의 서브 클래스?).

자바에서는 클래스에 배치하는 것을 피할 수 없습니다. 즉, 네임 스페이스와 모듈을 사용하는 것처럼 클래스를 사용해야하는 경우가 있습니다. 수학에 관한 많은 정적 메서드가 좋은 예입니다. 나는이 방법을 정적으로하는 것이 나쁜 상황에서 최선이라고 말한다.

정적 속성을 갖는 것이 "더티"인지 여부는 컨텍스트에 따라 크게 달라집니다. 정말로 알아야 할 것은 적절한 캡슐화입니다. 코드의 개념적 공간을 통해 곡선을 그릴 수 있으며 "이 측면의 모든 내용은 그 측면의 모든 것을 알 필요가 없습니다. 곡선

+1

파이썬에서 클래스 객체는 classobj (구식 클래스) 또는 type (새 스타일 클래스)의 * 인스턴스 *입니다. –

2

당신은 성능 및 메모리 관점에서 볼 수 있습니다 예를 들어, 다음 코드에서 :..

public class StringUtils 
{ 
    public static boolean isEmpty(String value) 
    { 
     // some code 
    } 

    public static String reverseString(String value) 
    { 
     // some code 
    } 
} 

당신이 정말 StringUtils에 인스턴스를 하시겠습니까 모든 장소 개체는 방법을 호출 어떤 멤버 변수도 저장하지 않는다? 간단한 프로그램에서는별로 중요하지 않다.그러나 일단 프로그램이 특정 크기가되기 시작하고 이러한 메서드를 수천 번 호출하면 인스턴스화를 추가 할 수 있습니다. 그리고 왜? 순정 주의자가 되려면? 그만한 가치는 없습니다. 같은 인스턴스를 사용하십시오.

+2

아니요, 이상적으로는 String의 메소드가되기를 원합니다. –

0

중앙 데이터 리포지토리가 필요한 멀티 스레드 응용 프로그램이 있다고 가정합니다. 소비자와 생산자는 저장소를 통해 인터페이스를 통해 저장소에 액세스하는 외부 응용 프로그램 개체를 포함하여 저장소에 데이터를 사용하거나 저장합니다.

이 저장소를 일반 클래스 개체로 만들면 개체를 초기화하고 필요한 모든 개체에 대한 포인터를 가져 오는 문제가 있습니다. 힘든 문제는 아니지만 많은 스레드와 객체로 인해 매우 혼란 스러울 수 있습니다. 한편

, 당신이 할 경우이 :

public enum Data implements MyInterface{ 
    INSTANCE; 
     private final Whatevertype secretstuff = new Whatevertype(); 
     ...etc... 
     public void PutThing(Sometype indata){ ... }; 
     public Sometype GetThing(int somecode){ ...}; 
     ...etc... 
} 

당신은 (a)와 (b)

Data.INSTANCE.GetThing(42); 

등으로 어디서나 액세스 할 수있는 모든 것을 인스턴스화 할 필요가 없습니다 그것은 Highlander와 같습니다 ... 오직 하나만있을 수 있습니다

+0

당신이 제안한 것처럼 전역 상태를 도입하면 악몽을 테스트 할 수 있습니다. – balu

관련 문제