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




15 Answers

진정한 대답은 여기 Jon Skeet입니다.

싱글 톤은 하나의 생성 된 인스턴스에 대한 액세스를 허용합니다. 인스턴스 (또는 인스턴스에 대한 참조)는 다른 메소드에 매개 변수로 전달되고 일반 객체로 처리 될 수 있습니다.

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

c# 싱글톤

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

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




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




정적 클래스 : -

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

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

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

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

  5. 우리는 C #에서 다른 정적 클래스에 정적 클래스를 상속받을 수 없습니다.

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

  7. 성능 향상 (정적 메서드는 컴파일 타임에 결합 됨)

하나씩 일어나는 것:-

  1. 하나의 오브젝트 인스턴스를 작성하여 재사용 할 수 있습니다.

  2. Singleton 인스턴스는 사용자가 요청할 때 처음으로 만들어집니다.

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

  4. 싱글 톤 클래스의 객체를 생성하여 메소드에 전달할 수 있습니다.

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

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

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

  8. 필요할 때 게으른로드가 가능합니다 (정적 클래스는 항상로드됩니다).

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




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

빠른 예 :

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



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




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

정적 클래스

  • static 메소드를 가지는 클래스
  • 더 나은 성능 (정적 메서드는 컴파일 타임에 결합 됨)
  • 메서드를 재정의 할 수는 없지만 메서드 숨기기를 사용할 수 있습니다. ( 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을 사용합니다.

편집




음, 싱글 톤은 IS가 인스턴스화되었지만 클라이언트 코드에서 간접적으로 한 번만 나타나는 정상적인 클래스입니다. 정적 클래스는 인스턴스화되지 않습니다. 내가 아는 한 정적 메소드 (정적 클래스는 정적 메소드가 있어야 함)는 정적이 아닌 것보다 빠릅니다.

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




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

아래 예제에서 이것을 설명 할 것입니다. 메소드 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 ()를 모의하기가 어렵습니다. 파워 모의로 정적을 조롱 할 수는 있지만 모든 제품에서 사용할 수있는 것은 아닙니다.




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

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

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

희망은 당신을 돕는 ..




  1. 게으른 로딩
  2. 별도의 구현을 제공 할 수 있도록 인터페이스 지원
  3. 파생 된 유형을 반환 할 수있는 기능 (lazyloading 및 인터페이스 구현의 조합)



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

  • 싱글 톤은 인스턴스 / 객체를 가지지 만, 정적 클래스는 정적 메소드의 묶음이다.
  • 싱글 톤은 정적 클래스가 될 수없는 인터페이스를 통해 확장 될 수 있습니다.
  • Singleton은 SOLID 원칙에서 open / close 원칙을 지원하는 반면, 정적 클래스는 상속 될 수 없으며, 자체적으로 변경해야합니다.
  • 인스턴스가 매개 변수로 전달 될 수 없으므로 정적 클래스는 메서드에 전달할 수 있습니다



클라이언트 관점에서 볼 때 정적 동작은 클라이언트에 알려져 있지만 Singleton 동작은 클라이언트에서 숨겨져 완료 될 수 있습니다. 클라이언트는 그가 반복적으로 놀고있는 하나의 인스턴스 만 있다는 것을 결코 알지 못할 수도 있습니다.




내가 쓴 기사에서 왜 싱글 톤이 정적 클래스보다 훨씬 나은지에 대한 제 관점을 설명했습니다 :

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



단일 정적 클래스 인스턴스 (즉, 클래스단일 인스턴스 (static 또는 global 변수))와 힙의 클래스 인스턴스에 대한 단일 정적 포인터 사이에는 큰 차이가 있습니다.

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




Static 클래스와 non-Static Singleton 클래스의 차이점을 이해했기 때문에 정적은 C #에서 인스턴스화되지 않은 "type"입니다. 여기서 Singleton은 진정한 "개체"입니다. 즉, 정적 클래스의 모든 정적 멤버는 유형에 할당되지만 Singleton에서는 해당 개체 아래에 배치됩니다. 그러나 정적 클래스는 여전히 Struct와 같은 값 유형이 아닌 참조 유형처럼 동작합니다.

즉, 클래스 자체가 정적이 아니기 때문에 싱글 톤을 만들었지 만 그 멤버가 있다는 장점은 자신을 참조하는 Singleton 내부의 정적 멤버가 자신의 빈 "유형"이 아닌 실제 "객체"에 연결된다는 것입니다. 그런 종류의 정적 및 비 정적 싱글 톤의 차이점은 다른 기능과 메모리 사용량을 넘어서서 혼란 스럽습니다.

둘 다 멤버의 단일 복사본 인 정적 멤버를 사용하지만 Singleton은 정적 멤버 이외에 주소가있는 인스턴스화 된 "개체"를 중심으로 참조 된 멤버를 래핑합니다. 그 객체 자체는 in을 전달하고 참조 할 수있는 속성을 가지고 있습니다. Static 클래스는 하나의 유형이므로 정적 멤버를 가리키는 경우를 제외하고는 존재하지 않습니다. 이 개념은 상속 및 기타 문제를 넘어서서 Singleton 대 정적 클래스의 목적을 확립했습니다.




Related