정적 클래스와 싱글 톤 패턴의 차이점은 무엇입니까?


1767

정적 클래스와 싱글 톤 패턴 사이에 실제 (실제) 차이는 무엇입니까?

둘 다 인스턴스화없이 호출 할 수 있으며, 하나의 "인스턴스"만 제공하며 둘 다 스레드로부터 안전하지 않습니다. 다른 차이점이 있습니까?


4
언어 구현 및 사용 패턴에 따라 사용 하려는 매번 메서드 를 호출하는 오버 헤드로 인해 Singleton의 효율성 떨어질 수 있습니다getInstance() (아마도 대부분의 경우 중요하지 않음 ).
너무 많은 PHP

5
이미 많은 답변이 있습니다. 그것은 사실이다 singleton오브젝트 static방법은 단지 기능, 비 OO 엔티티입니다.
fastcodejava

4
구현에 따라 다릅니다
VJAI

4
제 3자가 클래스 구현을 제공하도록 허용 할 때 차이가 있습니다. 이 경우 일반적으로 팩토리 패턴도 필요합니다. agiletribe.wordpress.com/2013/10/08/…
AgilePro

IMO이 답변은 아주 잘 요약합니다. stackoverflow.com/questions/14097656/…
Dave

답변:


1251

싱글 톤 또는 정적 메소드가 스레드로부터 안전하지 않다고 말하는 이유는 무엇입니까? 일반적으로 둘 다 스레드 안전하도록 구현 해야 합니다.

싱글 톤과 여러 정적 메소드의 가장 큰 차이점은 싱글 톤이 인터페이스를 구현할 수 있다는 것입니다 (또는 내 경험상 일반적이지 않지만 유용한 기본 클래스에서 파생 될 수 있음). "구현.


29
글쎄, 당신이 그것을 선호한다면, 본질적으로 스레드 안전도 아니고, 둘 다 스레드 안전해야하며 둘 다 다르므로 아무런 차이가 없습니다.
Jorge Córdoba

119
당신이 뭔가의 예를 줄 수 있다 불변의 유형 이외의 본질적으로 스레드를?
Jon Skeet

26
Skeet : 싱글 톤이 스레드 안전하지 않다는 사람들은 단일 톤이 불필요하게 스레드간에 항상 공유되는 반면 스택 객체는 필요할 때 공유되므로 불필요한 동기화를 수행 할 필요가 없음을 의미합니다.

45
@Geek : 싱글 톤이 interface를 구현 하고 매개 변수로 Foo메소드를 사용 한다고 상상해보십시오 Foo. 이 설정을 통해 호출자는 싱글 톤을 구현으로 사용하도록 선택하거나 다른 구현을 사용할 수 있습니다. 이 방법은 싱글 톤에서 분리됩니다. 클래스에 정적 메소드가있는 상황과 비교하십시오-정적 메소드를 포함하는 클래스를 지정해야하기 때문에 해당 메소드를 호출하려는 모든 코드는 클래스와 밀접하게 연결됩니다.
Jon Skeet

10
@ AmirBareket : 싱글 톤 디자인 패턴에 따르면 싱글 톤이 아닙니다. 클래스 자체가 여러 인스턴스를 만들 수 있다면 팩토리가하는 것과 상관없이 싱글 톤 IMO가 아닙니다.
Jon Skeet

476

정답은 Jon Skeet의 다른 포럼 입니다.

싱글 톤은 생성 된 단일 인스턴스에 대한 액세스를 허용합니다. 해당 인스턴스 (또는 인스턴스에 대한 참조)는 다른 메소드에 매개 변수로 전달되어 일반 오브젝트로 처리 될 수 있습니다.

정적 클래스는 정적 메소드 만 허용합니다.


64
정적 getInstance () 메소드를 호출하여 어디에서나 동일한 인스턴스에 액세스 할 수 있다면 왜 싱글 톤을 매개 변수로 전달하겠습니까?
Henrique Ordine

23
@HenriqueOrdine 기존 코드에 적합하고 인터페이스를 제공 할 수 있습니까?

6
@HenriqueOrdine 그들은 정적 메소드가 아닌 정적 클래스에 대해 이야기하고 있습니다. 정적 클래스는 인스턴스화 할 수 없습니다. 그럼에도 불구하고 정적 메서드가 포함 된 (비 정적) 클래스의 인스턴스를 전달하면 인스턴스에서 정적 메서드를 호출 할 수 없습니다.
Goran

3
정적 클래스는 무엇입니까? 적어도 자바에서는 그런 것이 없습니다.
Henrique Ordine

16
@Goran 나는 처음에 당신의 말에 매우 혼란 스러웠습니다. "인스턴스에서 정적 메소드를 호출 할 수 없습니다"라고 말했습니다. "인스턴스화 된 객체에 대한 참조가 있으면 정적 메서드를 호출 할 수 없습니다." 물론 그렇습니다. 몇 번 다시 읽은 후에는 "정적 메소드 내부에서 클래스의 비 정적 객체에 액세스 할 수 없음"을 의미한다고 생각합니다. 이 개념을 처음 접하는 사람이라면 누구나이 답변을보고 의견을 읽습니다.
Andrew Steitz

359
  1. 싱글 톤 객체는 에 저장 되지만 정적 객체는 스택에 저장됩니다 .
  2. 우리는 할 수 있습니다 복제 싱글 객체를 (디자이너는 그것을 허용하지 않은 경우), 그러나 우리는 정적 클래스의 객체가 아닌 복제 할 수 있습니다.
  3. 싱글 톤 클래스는 OOP (객체 지향 원칙)를 따르지만 정적 클래스는 그렇지 않습니다.
  4. interfaceSingleton 클래스를 사용하여를 구현할 수 있지만 클래스의 정적 메서드 (예 : C # static class)는 구현할 수 없습니다.

99
두 번째 진술이 잘못되었습니다. 싱글 톤 오브젝트를 복제 할 수 없습니다. 싱글 톤 구현은 이것을 거부해야합니다. 실제로 싱글 톤을 복제 할 수 있다면 싱글 톤이 아닙니다.
Alexander Yancharuk

19
이것은 정답이 아닙니다. Java에는 싱글 톤도 정적도 스택을 사용하지 않습니다.
AgilePro

72
# 1은 중요하지 않습니다. # 2는 결함이있는 구현을 설명합니다. # 3은 완전히 정당화 될 수 없습니다.
Casey

31
정적 객체를 스택에 어떻게 저장할 수 있습니까? 새 스택 프레임은 메서드를 호출 할 때 만들어지고 메서드의 로컬 변수를 저장하며이 스택 프레임은 메서드가 반환 될 때 제거되며 해당 로컬 변수가 손실됩니다. 확실한 스택은 빠르지 만 정적 객체를 저장하는 데 적합하지 않습니다.
mike_m 2016 년

23
나는 이것에 대한 공언의 수를 이해할 수 없다. 1) 왜 Singleton을 스택에 저장해야합니까? C # 또는 Java와 같은 관리 언어에서는 로컬 메소드 변수 / 매개 변수를 제외하고 관리 힙에 데이터가 저장됩니다. 2) 복제 할 수 있다면 제대로 구현 된 싱글 톤이 아닙니다. 3) 싱글 톤은 OOP 안티 패턴으로 알려져있다. 즉, 가능하면 피해야 할 것. 4) 이것이 유일한 것입니다.
Groo

152

싱글 톤 패턴은 정적 클래스에 비해 몇 가지 장점이 있습니다. 첫째, 단일 클래스는 클래스를 확장하고 인터페이스를 구현할 수 있지만 정적 클래스는 클래스를 확장 할 수는 있지만 인스턴스 멤버를 상속하지는 않습니다. 정적 클래스는 일반적으로 처음로드 될 때 초기화되는 동안 단일 클래스를 느리게 또는 비동기 적으로 초기화 할 수 있으므로 잠재적 인 클래스 로더 문제가 발생할 수 있습니다. 그러나 가장 중요한 장점은 사용자가 인스턴스가 하나만 있다고 가정하지 않고도 싱글 톤을 다형성으로 처리 할 수 ​​있다는 것입니다.


10
좋은 실용 포인트 +1. 싱글 톤 패턴은 일반적으로 과도하게 사용되지만 적합 할 경우가 있습니다. 참조 : agiletribe.wordpress.com/2013/10/08/...
AgilePro

3
당신은 다형성의 장점에 대해 옳습니다. 이것이 가장 중요한 점입니다
Ahmad

중첩 된 정적 클래스는 인터페이스를 구현할 수 있습니다. 코딩을 시도하면 효과가 있습니다. 오류없이 코드를 컴파일 할 수 있습니다.
nanosoft

75

static클래스는 상태가 필요한 것은 아닙니다. 많은 기능들을 한꺼번에 Math(또는 Utils프로젝트에서) 묶는 데 유용합니다 . 클래스 이름은 함수를 찾을 수있는 단서를 제공합니다.

Singleton내가 가장 좋아하는 패턴이며 한 지점에서 무언가를 관리하는 데 사용합니다. static클래스 보다 유연 하고 상태를 유지할 수 있습니다. 인터페이스를 구현하고 다른 클래스에서 상속하고 상속을 허용 할 수 있습니다.

static와 사이에서 선택하는 규칙 singleton:

함께 유지해야 할 기능이 많으면 static선택이 있습니다. 일부 리소스에 대한 단일 액세스가 필요한 다른 것은로 구현 될 수 있습니다 singleton.


16
정적 클래스가 상태를 저장하는 데 필요한 작업을 수행하지 않아야하는 이유는 무엇입니까?
Trisped

12
@Trisped : 초기화 나 마무리를 정확하게 제어 할 수 없습니다.
Xaqron

7
"싱글 톤은 내가 가장 좋아하는 패턴"입니다. 싱글턴은 패턴뿐만 아니라 안티 패턴으로 간주되어야하는 날카로운 모서리입니다. 대부분의 싱글 톤 구현이 깨져서 정적 상태가 싱글 톤보다 "단일 액세스"인 경우 클래스에는 정적 상태가있을 수 있습니다. 즉 단일 액세스이기도합니다. 정적은 독창적 인 정의로 축복받는 동안 싱글 톤을 복제 할 수 있습니다.
PoweredByRice

1
상태를 유지한다는 것은 무엇을 의미합니까? 상태 란?
Kyle Delaney

2
@KyleDelaney : 단순히 State시간이 지남에 따라 변하는 객체의 다양한 속성의 조합입니다. 공식적인 정의를 위해 Google을 사용할 수 있습니다.
Xaqron

65

정적 클래스 :-

  1. 정적 클래스의 인스턴스를 만들 수 없습니다.

  2. 클래스가 포함 된 프로그램 또는 네임 스페이스가로드 될 때 .NET Framework CLR (공용 언어 런타임)에 의해 자동으로로드됩니다.

  3. 정적 클래스는 생성자를 가질 수 없습니다.

  4. 정적 클래스를 메소드에 전달할 수 없습니다.

  5. C #에서 정적 클래스를 다른 정적 클래스로 상속 할 수 없습니다.

  6. 모든 정적 메서드가있는 클래스

  7. 더 나은 성능 (정적 메서드는 컴파일 타임에 결합됩니다)

하나씩 일어나는 것:-

  1. 객체의 한 인스턴스를 만들어 재사용 할 수 있습니다.

  2. 사용자가 처음 요청할 때 싱글 톤 인스턴스가 작성됩니다.

  3. 싱글 톤 클래스는 생성자를 가질 수 있습니다.

  4. 싱글 톤 클래스의 객체를 만들어 메소드에 전달할 수 있습니다.

  5. 싱글 톤 클래스는 상속의 제한을 말하지 않습니다.

  6. 정적 클래스가 아닌 싱글 톤 클래스의 객체를 처리 할 수 ​​있습니다.

  7. 메서드를 재정의 할 수 있습니다.

  8. 필요할 때 지연로드 될 수 있습니다 (정적 클래스는 항상로드 됨).

  9. 인터페이스를 구현할 수 있습니다 (정적 클래스는 인터페이스를 구현할 수 없음).


13
정적 클래스는 생성자를해야합니까 : msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
토 메르 Arazy

2
예, static에는 해당 클래스 내부에 생성자가있을 수 있습니다. 클래스의 정적 메소드가 호출 될 때 호출됩니다.
rahulmr

컴파일시 싱글 톤의 경우 HEAP 메모리에 저장되지만 한 번 인스턴스화되면 STACK에 저장됩니까?
Luminous_Dev

@Luminous_Dev 아니요. 싱글 톤 인스턴스는 하루가 끝날 때의 객체 인스턴스입니다. 의심의 여지없이 힙에 저장됩니다.
RBT

1
@rahulmr 중요한 차이점 : 첫 번째 (AKA 전용) 인스턴스가 생성되기 전에 생성자가 호출됩니다.
CoolOppo

53

정적 클래스는 더 나은 단어가 "함수"인 정적 메소드 만있는 클래스입니다. 정적 클래스로 구현 된 디자인 스타일은 순전히 절차 적입니다.

반면 싱글 톤은 OO 디자인에 특정한 패턴입니다. 그것은 전체 수명 동안 특정 역할의 인스턴스가 하나만 존재하도록 만드는 절차를 가진 (다형성과 같은 고유의 모든 가능성을 가진) 객체의 인스턴스입니다.


1
다형성은 싱글 톤으로 전혀 작동하지 않습니다

32
그래서 당신은 생각합니다. 다르게 생각합니다. ;) 예를 들어, 인터페이스를 반환하는 싱글 톤 팩토리를 상상해보십시오. ISingleton (그리고 영원히 같은 것)을 얻고 있지만 반드시 어떤 구현을 요구하지는 않습니다.
Morendil

중첩 된 정적 클래스는 인스턴스 메소드도 가질 수 있으며 정적 메소드 만있는 것으로 제한되지는 않습니다. 코드화하면 알 수 있습니다.
nanosoft

객체 모델이 더 좋은 언어 (예 : 루비)에서는 클래스도 객체입니다. 정적 클래스의 "순전히 절차 적"측면은 언어에 의해 부과되는 임의의 제한입니다.
Max

36

싱글 톤 패턴에서는 싱글 톤을 파생 유형의 인스턴스로 만들 수 있으며 정적 클래스로는 싱글 톤을 만들 수 없습니다.

빠른 예 :

if( useD3D )
    IRenderer::instance = new D3DRenderer
else
    IRenderer::instance = new OpenGLRenderer

39
그것은 실제로 싱글 톤 패턴이 아니며 공장처럼 보입니다.
vava

10
실제로이 둘의 근본적인 차이점은 싱글 톤이 단일 객체를 "캐시"하고 동일한 객체를 계속 반환한다는 것입니다. 팩토리 패턴은 새 인스턴스를 만듭니다.
Mystic

12
그렇다면 그것은 프록시-싱글턴입니다 :)
vava

3
흠, 나는 이러한 다양한 싱글 톤을 MonoState로 알고 있습니다.
Huppie

예는 공장 패턴입니다
Rajavel D

26

Jon Skeet의 답변 을 확장하려면

싱글 톤과 여러 정적 메소드의 큰 차이점은 싱글 톤이 인터페이스를 구현할 수 있다는 것입니다 (또는 일반적인 IME는 아니지만 유용한 기본 클래스에서 파생 됨). "단지 다른"구현 인 것처럼 싱글 톤을 전달할 수 있습니다.

클래스를 테스트 할 때 싱글 톤으로 작업하기가 더 쉽습니다. 싱글 톤을 매개 변수 (생성자, 설정자 또는 메소드)로 전달할 때 모의 또는 스텁 된 싱글 톤 버전을 대신 사용할 수 있습니다.


싱글 톤을 직접 조롱 할 수는 없다고 생각합니다. 싱글 톤과 모의 클래스가 모두 구현하는 인터페이스를 선언하지 않아도됩니까?
Ellen Spertus

@espertus 왜 싱글 톤을 조롱 할 수 없습니까? mockito를 사용하는 예제 MySingleton mockOfMySingleton = mock(MySingleton.class).
Mike Rylander

맞습니다. 리플렉션을 사용하는 mockito와 같은 도구로 그것을 조롱 할 수 있습니다. 하위 클래스를 만들고 메서드를 재정 의하여 직접 조롱 할 수 없다는 것을 의미했습니다.
Ellen Spertus

@espertus 왜 안돼? 테스트중인 객체를 인스턴스화 할 때 원본을 사용한 위치에 싱글 톤의 서브 클래스 구현을 대체 할 수 있습니다. 예 :new ClazzToTest(mockSingleton);
Mike Rylander

Mockito를 사용하지는 않았지만 개인 생성자를 가진 클래스를 어떻게 서브 클래스 화 할 수 있습니까? 반사를 사용하지 않는 한 싱글 톤의 경우입니까? 관련 토론 : stackoverflow.com/questions/2302179/mocking-a-singleton-class stackoverflow.com/questions/15939023/...
엘렌 스퍼터 스

23

좋은 기사가 있습니다 : http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

정적 클래스

  • 모든 정적 메소드를 갖는 클래스 .
  • 더 나은 성능 (정적 메소드는 컴파일 타임에 결합됩니다)
  • 메서드를 재정의 할 수는 없지만 메서드 숨기기를 사용할 수 있습니다. ( Java에서 메소드 숨기기는 무엇입니까? JavaDoc 설명조차도 혼란 스럽습니다 )

    public class Animal {
        public static void foo() {
            System.out.println("Animal");
        }
    }
    
    public class Cat extends Animal {
        public static void foo() {  // hides Animal.foo()
            System.out.println("Cat");
        }
    }
    

하나씩 일어나는 것

요약하면, 나는 util 메소드를 유지하고 다른 모든 것에 Singleton을 사용하기 위해 정적 클래스 만 사용합니다.


편집


4
Java에 대해서는 잘 모르지만 .Net에서 마지막 두 지점이 잘못되었습니다. 정적 클래스는 정적 속성 및 필드를 참조 할 수 있으므로 동일한 상태입니다. 그리고 정적 로딩은 다음과 같은 경우에 실행됩니다 : 1) 클래스의 인스턴스가 생성됩니다. 2) 클래스의 정적 멤버가 참조됩니다. 1은 적용되지 않고 2를 남깁니다. 따라서 정적 클래스는 처음 사용될 때까지로드되지 않습니다.
jmoreno

1
정적 클래스의 경우 정적 메서드를 재정의 할 수 없지만 정적 메서드를 부모에서 숨길 수 있습니다.
Max Peng

경우 Animal animal = new Cat();다음 animal.foo();무슨 일이 일어나는가?
Luminous_Dev

@jmoreno 정적 클래스는 처음 사용할 때까지로드되지 않습니까? 컴파일 타임에 스택 메모리에 저장되어 있다고 생각합니다. 그리고 그것은 즉시 액세스됩니다.
Luminous_Dev

@Luminous_Dev : 적어도 .net의 경우 정적 클래스에는 처음 액세스 할 때 실행되는 생성자가 있으므로 즉시 액세스 할 수 없습니다. 정적 생성자는 이론적으로 무한한 시간이 걸릴 수 있습니다. 그것이 (또는 다른 클래스가 저장되는) 구현 세부 사항 인 경우 실제로이 질문과 관련이 없습니다.
jmoreno

22

싱글 톤의 또 다른 장점은 쉽게 직렬화 할 수 있다는 것입니다. 상태를 디스크에 저장하거나 원격으로 보내야 할 경우 필요할 수 있습니다.


19

나는 훌륭한 OO 이론가는 아니지만, 내가 아는 한, 정적 클래스가 싱글 톤에 비해 부족한 유일한 OO 기능은 다형성이라고 생각합니다. 그러나 필요하지 않은 경우 정적 클래스를 사용하면 상속 (인터페이스 구현에 대해 확실하지 않음) 및 데이터 및 함수 캡슐화를 가질 수 있습니다.

Morendil의 의견은 "정적 클래스로 구현 된 디자인 스타일은 순전히 절차 적입니다"라고 잘못 생각할 수도 있지만 동의하지 않습니다. 정적 메서드에서는 정적 멤버에 액세스 할 수 있습니다. 정적 멤버는 단일 인스턴스 멤버에 액세스하는 단일 메서드와 동일합니다.

편집 :
실제로 다른 차이점은 정적 클래스가 인스턴스화 된다는 것입니다. 프로그램 시작 *에서 되고 프로그램의 전체 수명 기간 동안 살아남고 단일 톤은 특정 시점에서 명시 적으로 인스턴스화되어 파괴 될 수 있다는 것입니다.

* 또는 언어에 따라 처음 사용할 때 인스턴스화 될 수 있다고 생각합니다.


15
그렇습니다. 다른 사람들은 정적 메소드가있는 클래스에도 여전히 상태를 유지하는 데 사용할 수있는 개인 정적 필드를 가질 수 있다는 사실을 무시하는 것 같습니다 (공개 정적 setter / getter를 통해 클라이언트 코드에 일부를 노출시킵니다).
user289463

17

Jon의 요점을 설명하기 위해 Logger가 정적 클래스 인 경우 아래에 표시된 내용을 수행 할 수 없습니다. 클래스 SomeClassILogger구현 인스턴스가 생성자에 전달 될 것으로 예상합니다 .

의존성 주입이 가능하려면 싱글 톤 클래스가 중요합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            var someClass = new SomeClass(Logger.GetLogger());
        }


    }

    public class SomeClass 
    {
        public SomeClass(ILogger MyLogger)
        {

        }
    }

    public class Logger : ILogger
    {
        private static Logger _logger;
        private Logger() { }

        public static Logger GetLogger()
        {
            if (_logger==null)
            {
                _logger = new Logger();
            }

            return _logger;
        }

        public void Log()
        {

        }

    }


    public interface ILogger
    {
         void Log();
    }
}

13

싱글 톤은 클라이언트 코드에서 한 번만 간접적으로 인스턴스화되는 일반 클래스 일뿐입니다. 정적 클래스가 인스턴스화되지 않았습니다. 내가 아는 한 정적 메소드 (정적 클래스에는 정적 메소드가 있어야 함)가 비 정적보다 빠릅니다.

편집 :
FxCop 성능 규칙 설명 : "인스턴스 데이터에 액세스하지 않거나 인스턴스 메소드를 호출하는 메소드는 정적 (VB에서 공유)로 표시 될 수 있습니다. 그렇게하면 컴파일러가 비가 상 호출 사이트를이 멤버에 내 보내서 현재 객체 포인터가 널이 아닌지 확인하는 각 호출에 대해 런타임시 점검하십시오. 이는 성능에 민감한 코드의 성능을 측정 할 수 있습니다. 경우에 따라 현재 객체 인스턴스에 액세스하지 못하면 정확성 문제가 발생합니다. "
실제로 이것이 정적 클래스의 정적 메소드에도 적용되는지는 알 수 없습니다.


11

싱글 톤은 인스턴스화됩니다. 인스턴스화 된 인스턴스는 단 하나뿐이므로 단일 싱글 톤 .

정적 클래스는 자체 이외의 다른 것으로 인스턴스화 할 수 없습니다.


정적 클래스는 java에서 매우 인스턴스화 될 수 있습니다. docs.oracle.com/javase/tutorial/java/javaOO/nested.html을 읽으십시오. 또한 내 답변을 참조하십시오 stackoverflow.com/a/37114702/1406510
nanosoft

8

주요 차이점은 다음과 같습니다.

  • Singleton에는 인스턴스 / 객체가 있고 정적 클래스는 정적 메서드입니다.
  • 정적 클래스는 할 수 없지만 인터페이스를 통해 싱글 톤을 확장 할 수 있습니다.
  • SOLID 원칙에서 개방 / 폐쇄 원칙을 지원하는 싱글 톤은 상속 될 수 있지만 정적 클래스는 상속 될 수 없으므로 자체적으로 변경해야합니다.
  • 인스턴스가없는 정적 클래스는 매개 변수로 전달할 수 없으므로 정적 클래스를 사용하는 동안 Singleton 객체를 메서드에 전달할 수 있습니다.

7

싱글 톤은 테스트 관점에서 더 나은 접근 방식입니다. 정적 클래스와 달리 싱글 톤은 인터페이스를 구현할 수 있으며 모의 인스턴스를 사용하여 주입 할 수 있습니다.

아래 예에서이를 설명하겠습니다. getPrice () 메소드를 사용하는 isGoodPrice () 메소드가 있고 단일 톤의 메소드로 getPrice ()를 구현한다고 가정하십시오.

getPrice 기능을 제공하는 싱글 톤 :

public class SupportedVersionSingelton {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        // calculate price logic here
        return 0;
    }
}

getPrice 사용 :

public class Advisor {

    public boolean isGoodDeal(){

        boolean isGoodDeal = false;
        ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
        int price = supportedVersion.getPrice();

        // logic to determine if price is a good deal.
        if(price < 5){
            isGoodDeal = true;
        }

        return isGoodDeal;
    }
}


In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it. 



  public interface ICalculator {
        int getPrice();
    }

최종 싱글 톤 구현 :

public class SupportedVersionSingelton implements ICalculator {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        return 0;
    }

    // for testing purpose
    public static void setInstance(ICalculator mockObject){
        if(instance != null ){
instance = mockObject;
    }

시험 수업 :

public class TestCalculation {

    class SupportedVersionDouble implements ICalculator{
        @Override
        public int getPrice() { 
            return 1;
        }   
    }
    @Before
    public void setUp() throws Exception {
        ICalculator supportedVersionDouble = new SupportedVersionDouble();
        SupportedVersionSingelton.setInstance(supportedVersionDouble);

    }

    @Test
    public void test() {
          Advisor advidor = new Advisor();
          boolean isGoodDeal = advidor.isGoodDeal();
          Assert.assertEquals(isGoodDeal, true);

    }

}

getPrice () 구현을 위해 정적 메소드를 사용하는 대안을 사용하는 경우 getPrice ()를 모의하기가 어려웠습니다. power mock을 사용하여 static을 조롱 할 수 있지만 모든 제품에서이를 사용할 수는 없습니다.


1
이제는 스레드로부터 안전하지 않으며 일반적으로 인터페이스 구현에 액세스하는 방식에있어 불쾌합니다. 물론, 인터페이스를 갖는 것은 테스트 가능성에 좋지만, 왜 싱글 톤으로 귀찮게합니까? 싱글 톤을 사용하지 마십시오. 프로덕션 목적으로 구현하는 클래스 하나와 테스트 목적으로 구현 한 클래스 하나를 만들고 수행중인 작업에 따라 올바른 인스턴스를 주입하십시오. 싱글 톤을 호출자와 전혀 연결할 필요가 없습니다.
Jon Skeet

피드백을 주셔서 감사합니다. 스레드를 안전하게 만드는 것은 매우 간단합니다. 또한 캐싱 목적으로 싱글 톤을 사용합니다.
Amir Bareket

1
예, 무의미한 오버 헤드가 있지만. 다시 한번, 싱글 톤을 사용하지 않는 것이 더 간단합니다.
Jon Skeet

6

나는이 정의에 동의한다 :

" 단일 "이라는 단어 " 는 응용 프로그램 수명주기에서 단일 개체를 의미하므로 범위는 응용 프로그램 수준에 있습니다.

정적 범위는 응용 프로그램 도메인 수준에서 그래서, 어떤 개체 포인터를 가지고 있지 않습니다.

또한 둘 다 스레드로부터 안전하도록 구현되어야합니다.

다음과 같은 흥미로운 다른 차이점을 찾을 수 있습니다. 정적 클래스와 단일 클래스


5

주목할만한 차이점 중 하나는 싱글 톤과 함께 제공되는 다른 인스턴스입니다.

정적 클래스를 사용하면 CLR에 의해 생성되며 제어 할 수 없습니다. 싱글 톤을 사용하면 액세스하려는 첫 번째 인스턴스에서 객체가 인스턴스화됩니다.


4

대부분의 경우,이 두 인스턴스는 실질적인 차이가 없습니다. 특히 싱글 톤 인스턴스가 구성 유지와 같이 매우 느리게 변경되거나 변경되지 않는 경우에는 더욱 그렇습니다.

가장 큰 차이점은 특수 정적 정적 Java 클래스와 달리 싱글 톤이 여전히 일반적인 Java Bean이라는 것입니다. 그리고 이로 인해 더 많은 상황에서 싱글 톤이 허용됩니다. 실제로 기본 스프링 프레임 워크의 인스턴스화 전략입니다. 소비자는 단일 톤이 전달되고 있다는 것을 알거나 알 수 없으며 단지 일반 Java Bean처럼 취급합니다. Spring에서 자주 볼 수 있듯이 요구 사항이 변경되고 단일 항목이 프로토 타입이되어야하는 경우 소비자에 대한 코드 변경없이 완벽하게 수행 할 수 있습니다.

다른 누군가는 정적 클래스가 순전히 절차 적이어야한다고 언급했습니다 (예 : java.lang.Math). 내 마음에, 그런 클래스는 절대로 전달되어서는 안되며 정적 결승 이외의 속성을 보유해서는 안됩니다. 그 밖의 모든 것에는 싱글 톤을 사용하면 훨씬 유연하고 유지 관리가 쉽습니다.


4

백엔드에 연결하는 DB 프레임 워크가 있습니다. 여러 사용자에 대한 더티 읽기를 방지하기 위해 단일 인스턴스를 사용하여 언제든지 단일 인스턴스를 사용할 수 있습니다.

C #에서 정적 클래스는 인터페이스를 구현할 수 없습니다. 단일 인스턴스 클래스가 비즈니스 계약 또는 IoC 목적으로 인터페이스를 구현해야하는 경우 정적 클래스없이 Singleton 패턴을 사용합니다.

싱글 톤은 상태 비 저장 시나리오에서 상태를 유지하는 방법을 제공합니다

도움이 되길 바랍니다 ..


3
  1. 게으른 로딩
  2. 별도의 구현이 가능하도록 인터페이스 지원
  3. 파생 유형을 반환하는 기능 (지연 로딩 및 인터페이스 구현의 조합으로)

중첩 정적 클래스는 Java에서 인터페이스를 매우 많이 구현할 수 있습니다. 두 번째 요점이 잘못되었습니다.
nanosoft

3

ㅏ. 직렬화-정적 멤버는 클래스에 속하므로 직렬화 할 수 없습니다.

비. 우리는 생성자를 private로 만들었지 만 정적 멤버 변수는 여전히 하위 클래스로 전달됩니다.

씨. 클래스 로딩시에만 모든 것이로드되므로 지연 초기화를 수행 할 수 없습니다.


3

클라이언트 관점에서 정적 동작은 클라이언트에게 알려져 있지만 클라이언트에서 싱글 톤 동작을 숨겨서 완료 할 수 있습니다. 고객은 자신이 계속해서 놀고있는 하나의 인스턴스 만 있다는 것을 절대 알 수 없습니다.


3

나는 다음을 읽고 그것이 의미가 있다고 생각합니다.

사업 관리

가장 중요한 OO 규칙 중 하나는 객체가 자신을 책임진다는 것입니다. 즉, 클래스의 수명주기와 관련된 문제는 정적과 같은 언어 구문으로 위임되지 않고 클래스에서 처리되어야합니다.

Objected-Oriented Thought Process 4th Ed.


이것은 실제로 수업에 책임을 부여하기 때문에 동의하지 않을 것입니다.
ssmith

3

내가 쓴 기사에서 싱글 톤이 정적 클래스보다 훨씬 나은 이유에 대한 내 견해를 설명했습니다.

  1. 정적 클래스는 실제로 표준 클래스가 아닙니다. 함수와 변수가있는 네임 스페이스입니다.
  2. 객체 지향 프로그래밍 원칙을 깨기 때문에 정적 클래스를 사용하는 것은 좋은 습관이 아닙니다.
  3. 정적 클래스는 다른 매개 변수로 전달할 수 없습니다
  4. 정적 클래스는 "게으른"초기화에 적합하지 않습니다
  5. 정적 클래스의 초기화 및 사용은 항상 하드 추적
  6. 스레드 관리 구현이 어렵다

나는 영어 문법을 위해 그것을
닦을

3
  1. 싱글 톤 클래스의 객체를 만들어 메소드에 전달할 수 있습니다.

  2. 싱글 톤 클래스는 상속을 제한하지 않습니다.

  3. 정적 클래스의 객체를 처분 할 수는 없지만 싱글 톤 클래스는 할 수 있습니다.


항상 하나만 있고 항상 정적 참조가있는 경우 싱글 톤을 메소드에 전달하는 방법은 무엇입니까?
Aaron Franke

3

정적 클래스와 구별

JDK에는 싱글 톤과 정적의 예가 있으며, 한편으로 java.lang.Math는 정적 메소드가있는 최종 클래스입니다.java.lang.Runtime 으로는 싱글 톤 클래스입니다.

싱글 톤의 장점

  • 정적 클래스에서 상태를 유지 관리하는 것이 버그, 특히 동시 환경에서 여러 스레드에 의한 적절한 병렬 병렬 수정없이 경쟁 조건으로 이어질 수 있기 때문에 싱글 톤 패턴보다 상태를 유지해야하는 것이 정적 클래스보다 더 나은 선택입니다.

  • 단일 객체 클래스는 무거운 객체 인 경우 지연로드 될 수 있지만 정적 클래스에는 이러한 장점이 없으며 항상 열심히로드됩니다.

  • 싱글 톤을 사용하면 상속 및 다형성을 사용하여 기본 클래스를 확장하고 인터페이스를 구현하며 다른 구현을 제공 할 수 있습니다.

  • Java의 정적 메소드는 대체 할 수 없으므로 융통성이 없습니다. 반면 싱글 톤 클래스에 정의 된 메소드를 확장하여이를 대체 할 수 있습니다.

정적 클래스의 단점

  • 싱글 톤이 필요할 때마다 모의 객체를 전달할 수 있기 때문에 정적 클래스보다 싱글 톤에 대한 단위 테스트를 작성하는 것이 더 쉽습니다.

정적 클래스의 장점

  • 정적 클래스는 컴파일 타임에 결합되므로 정적 클래스는 싱글 톤보다 더 나은 성능을 제공합니다.

각각의 장점과 단점이있는 싱글 톤 패턴의 구현이 몇 가지 있습니다.

  • 열망 로딩 싱글 톤
  • 이중 확인 잠금 싱글 톤
  • 주문형 홀더 관용구 초기화
  • 열거 형 기반 싱글 톤

그들 각각에 대한 자세한 설명은 너무 장황하므로 그냥 좋은 기사에 대한 링크를 넣어 -Singleton에 대해 알고 싶은 모든 것


2

단일 정적 클래스 인스턴스 (정적 또는 전역 변수가되는 클래스의 단일 인스턴스)와 단일 정적 포인터 간에는 큰 차이 가 있습니다. 힙의 클래스 인스턴스에 .

애플리케이션이 종료되면 정적 클래스 인스턴스의 소멸자가 호출됩니다. 즉, 정적 인스턴스를 싱글 톤으로 사용하면 싱글 톤이 제대로 작동하지 않습니다. 예를 들어 다른 스레드에서 해당 싱글 톤을 사용하는 코드가 여전히 실행중인 경우 해당 코드가 충돌 할 수 있습니다.


1
응용 프로그램이 종료되면 Singleton이 여전히 메모리에 남아 있습니까?
nanosoft

응용 프로그램이 아닌 현재 스레드가 종료되는 것을 의미한다고 생각합니까? 응용 프로그램이 종료되면 다른 스레드가 응용 프로그램에서 아무것도 사용할 수 없습니다.
톰 브리토

2

내 머리의 차이점은 객체 지향 프로그래밍 (Singleton / Prototype) 또는 기능적 프로그래밍 (Static)을 구현하는 것입니다.

우리가 집중해야 할 것이 결국 객체를 보유하고있을 때 싱글 톤 패턴으로 생성 된 객체의 수에 너무 집중하고 있습니다. 다른 사람들이 이미 말했듯이, 확장되고 매개 변수로 전달 될 수 있지만 가장 중요한 것은 상태가 가득 찼습니다.

반면에 static은 함수형 프로그래밍을 구현하는 데 사용됩니다. 정적 멤버는 클래스에 속합니다. 그들은 무국적자입니다.

그건 그렇고 당신은 싱글 톤 정적 클래스를 만들 수 있다는 것을 알고 있습니다 :)


클래스에 대한 정적 참조가 항상 있기 때문에 싱글 톤을 매개 변수로 전달하는 요점은 무엇입니까?
Aaron Franke
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.