정적 클래스와 싱글 톤 패턴 사이에 실제 (실제) 차이는 무엇입니까?
둘 다 인스턴스화없이 호출 할 수 있으며, 하나의 "인스턴스"만 제공하며 둘 다 스레드로부터 안전하지 않습니다. 다른 차이점이 있습니까?
singleton
오브젝트 static
방법은 단지 기능, 비 OO 엔티티입니다.
정적 클래스와 싱글 톤 패턴 사이에 실제 (실제) 차이는 무엇입니까?
둘 다 인스턴스화없이 호출 할 수 있으며, 하나의 "인스턴스"만 제공하며 둘 다 스레드로부터 안전하지 않습니다. 다른 차이점이 있습니까?
singleton
오브젝트 static
방법은 단지 기능, 비 OO 엔티티입니다.
답변:
싱글 톤 또는 정적 메소드가 스레드로부터 안전하지 않다고 말하는 이유는 무엇입니까? 일반적으로 둘 다 스레드 안전하도록 구현 해야 합니다.
싱글 톤과 여러 정적 메소드의 가장 큰 차이점은 싱글 톤이 인터페이스를 구현할 수 있다는 것입니다 (또는 내 경험상 일반적이지 않지만 유용한 기본 클래스에서 파생 될 수 있음). "구현.
Foo
메소드를 사용 한다고 상상해보십시오 Foo
. 이 설정을 통해 호출자는 싱글 톤을 구현으로 사용하도록 선택하거나 다른 구현을 사용할 수 있습니다. 이 방법은 싱글 톤에서 분리됩니다. 클래스에 정적 메소드가있는 상황과 비교하십시오-정적 메소드를 포함하는 클래스를 지정해야하기 때문에 해당 메소드를 호출하려는 모든 코드는 클래스와 밀접하게 연결됩니다.
정답은 Jon Skeet의 다른 포럼 입니다.
싱글 톤은 생성 된 단일 인스턴스에 대한 액세스를 허용합니다. 해당 인스턴스 (또는 인스턴스에 대한 참조)는 다른 메소드에 매개 변수로 전달되어 일반 오브젝트로 처리 될 수 있습니다.
정적 클래스는 정적 메소드 만 허용합니다.
interface
Singleton 클래스를 사용하여를 구현할 수 있지만 클래스의 정적 메서드 (예 : C # static class
)는 구현할 수 없습니다.싱글 톤 패턴은 정적 클래스에 비해 몇 가지 장점이 있습니다. 첫째, 단일 클래스는 클래스를 확장하고 인터페이스를 구현할 수 있지만 정적 클래스는 클래스를 확장 할 수는 있지만 인스턴스 멤버를 상속하지는 않습니다. 정적 클래스는 일반적으로 처음로드 될 때 초기화되는 동안 단일 클래스를 느리게 또는 비동기 적으로 초기화 할 수 있으므로 잠재적 인 클래스 로더 문제가 발생할 수 있습니다. 그러나 가장 중요한 장점은 사용자가 인스턴스가 하나만 있다고 가정하지 않고도 싱글 톤을 다형성으로 처리 할 수 있다는 것입니다.
static
클래스는 상태가 필요한 것은 아닙니다. 많은 기능들을 한꺼번에 Math
(또는 Utils
프로젝트에서) 묶는 데 유용합니다 . 클래스 이름은 함수를 찾을 수있는 단서를 제공합니다.
Singleton
내가 가장 좋아하는 패턴이며 한 지점에서 무언가를 관리하는 데 사용합니다. static
클래스 보다 유연 하고 상태를 유지할 수 있습니다. 인터페이스를 구현하고 다른 클래스에서 상속하고 상속을 허용 할 수 있습니다.
static
와 사이에서 선택하는 규칙 singleton
:
함께 유지해야 할 기능이 많으면 static
선택이 있습니다. 일부 리소스에 대한 단일 액세스가 필요한 다른 것은로 구현 될 수 있습니다 singleton
.
State
시간이 지남에 따라 변하는 객체의 다양한 속성의 조합입니다. 공식적인 정의를 위해 Google을 사용할 수 있습니다.
정적 클래스 :-
정적 클래스의 인스턴스를 만들 수 없습니다.
클래스가 포함 된 프로그램 또는 네임 스페이스가로드 될 때 .NET Framework CLR (공용 언어 런타임)에 의해 자동으로로드됩니다.
정적 클래스는 생성자를 가질 수 없습니다.
정적 클래스를 메소드에 전달할 수 없습니다.
C #에서 정적 클래스를 다른 정적 클래스로 상속 할 수 없습니다.
모든 정적 메서드가있는 클래스
더 나은 성능 (정적 메서드는 컴파일 타임에 결합됩니다)
하나씩 일어나는 것:-
객체의 한 인스턴스를 만들어 재사용 할 수 있습니다.
사용자가 처음 요청할 때 싱글 톤 인스턴스가 작성됩니다.
싱글 톤 클래스는 생성자를 가질 수 있습니다.
싱글 톤 클래스의 객체를 만들어 메소드에 전달할 수 있습니다.
싱글 톤 클래스는 상속의 제한을 말하지 않습니다.
정적 클래스가 아닌 싱글 톤 클래스의 객체를 처리 할 수 있습니다.
메서드를 재정의 할 수 있습니다.
필요할 때 지연로드 될 수 있습니다 (정적 클래스는 항상로드 됨).
인터페이스를 구현할 수 있습니다 (정적 클래스는 인터페이스를 구현할 수 없음).
정적 클래스는 더 나은 단어가 "함수"인 정적 메소드 만있는 클래스입니다. 정적 클래스로 구현 된 디자인 스타일은 순전히 절차 적입니다.
반면 싱글 톤은 OO 디자인에 특정한 패턴입니다. 그것은 전체 수명 동안 특정 역할의 인스턴스가 하나만 존재하도록 만드는 절차를 가진 (다형성과 같은 고유의 모든 가능성을 가진) 객체의 인스턴스입니다.
싱글 톤 패턴에서는 싱글 톤을 파생 유형의 인스턴스로 만들 수 있으며 정적 클래스로는 싱글 톤을 만들 수 없습니다.
빠른 예 :
if( useD3D )
IRenderer::instance = new D3DRenderer
else
IRenderer::instance = new OpenGLRenderer
Jon Skeet의 답변 을 확장하려면
싱글 톤과 여러 정적 메소드의 큰 차이점은 싱글 톤이 인터페이스를 구현할 수 있다는 것입니다 (또는 일반적인 IME는 아니지만 유용한 기본 클래스에서 파생 됨). "단지 다른"구현 인 것처럼 싱글 톤을 전달할 수 있습니다.
클래스를 테스트 할 때 싱글 톤으로 작업하기가 더 쉽습니다. 싱글 톤을 매개 변수 (생성자, 설정자 또는 메소드)로 전달할 때 모의 또는 스텁 된 싱글 톤 버전을 대신 사용할 수 있습니다.
MySingleton mockOfMySingleton = mock(MySingleton.class)
.
new ClazzToTest(mockSingleton);
좋은 기사가 있습니다 : 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을 사용하기 위해 정적 클래스 만 사용합니다.
편집
정적 클래스도 지연로드됩니다. 감사합니다 @jmoreno ( 정적 클래스 초기화는 언제 발생합니까? )
정적 클래스에 대한 메소드 숨기기. @MaxPeng에게 감사합니다.
Animal animal = new Cat();
다음 animal.foo();
무슨 일이 일어나는가?
나는 훌륭한 OO 이론가는 아니지만, 내가 아는 한, 정적 클래스가 싱글 톤에 비해 부족한 유일한 OO 기능은 다형성이라고 생각합니다. 그러나 필요하지 않은 경우 정적 클래스를 사용하면 상속 (인터페이스 구현에 대해 확실하지 않음) 및 데이터 및 함수 캡슐화를 가질 수 있습니다.
Morendil의 의견은 "정적 클래스로 구현 된 디자인 스타일은 순전히 절차 적입니다"라고 잘못 생각할 수도 있지만 동의하지 않습니다. 정적 메서드에서는 정적 멤버에 액세스 할 수 있습니다. 정적 멤버는 단일 인스턴스 멤버에 액세스하는 단일 메서드와 동일합니다.
편집 :
실제로 다른 차이점은 정적 클래스가 인스턴스화 된다는 것입니다. 프로그램 시작 *에서 되고 프로그램의 전체 수명 기간 동안 살아남고 단일 톤은 특정 시점에서 명시 적으로 인스턴스화되어 파괴 될 수 있다는 것입니다.
* 또는 언어에 따라 처음 사용할 때 인스턴스화 될 수 있다고 생각합니다.
Jon의 요점을 설명하기 위해 Logger가 정적 클래스 인 경우 아래에 표시된 내용을 수행 할 수 없습니다. 클래스 SomeClass
는 ILogger
구현 인스턴스가 생성자에 전달 될 것으로 예상합니다 .
의존성 주입이 가능하려면 싱글 톤 클래스가 중요합니다.
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();
}
}
싱글 톤은 클라이언트 코드에서 한 번만 간접적으로 인스턴스화되는 일반 클래스 일뿐입니다. 정적 클래스가 인스턴스화되지 않았습니다. 내가 아는 한 정적 메소드 (정적 클래스에는 정적 메소드가 있어야 함)가 비 정적보다 빠릅니다.
편집 :
FxCop 성능 규칙 설명 : "인스턴스 데이터에 액세스하지 않거나 인스턴스 메소드를 호출하는 메소드는 정적 (VB에서 공유)로 표시 될 수 있습니다. 그렇게하면 컴파일러가 비가 상 호출 사이트를이 멤버에 내 보내서 현재 객체 포인터가 널이 아닌지 확인하는 각 호출에 대해 런타임시 점검하십시오. 이는 성능에 민감한 코드의 성능을 측정 할 수 있습니다. 경우에 따라 현재 객체 인스턴스에 액세스하지 못하면 정확성 문제가 발생합니다. "
실제로 이것이 정적 클래스의 정적 메소드에도 적용되는지는 알 수 없습니다.
싱글 톤은 인스턴스화됩니다. 인스턴스화 된 인스턴스는 단 하나뿐이므로 단일 싱글 톤 .
정적 클래스는 자체 이외의 다른 것으로 인스턴스화 할 수 없습니다.
싱글 톤은 테스트 관점에서 더 나은 접근 방식입니다. 정적 클래스와 달리 싱글 톤은 인터페이스를 구현할 수 있으며 모의 인스턴스를 사용하여 주입 할 수 있습니다.
아래 예에서이를 설명하겠습니다. 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을 조롱 할 수 있지만 모든 제품에서이를 사용할 수는 없습니다.
나는이 정의에 동의한다 :
" 단일 "이라는 단어 " 는 응용 프로그램 수명주기에서 단일 개체를 의미하므로 범위는 응용 프로그램 수준에 있습니다.
정적 범위는 응용 프로그램 도메인 수준에서 그래서, 어떤 개체 포인터를 가지고 있지 않습니다.
또한 둘 다 스레드로부터 안전하도록 구현되어야합니다.
다음과 같은 흥미로운 다른 차이점을 찾을 수 있습니다. 정적 클래스와 단일 클래스
주목할만한 차이점 중 하나는 싱글 톤과 함께 제공되는 다른 인스턴스입니다.
정적 클래스를 사용하면 CLR에 의해 생성되며 제어 할 수 없습니다. 싱글 톤을 사용하면 액세스하려는 첫 번째 인스턴스에서 객체가 인스턴스화됩니다.
대부분의 경우,이 두 인스턴스는 실질적인 차이가 없습니다. 특히 싱글 톤 인스턴스가 구성 유지와 같이 매우 느리게 변경되거나 변경되지 않는 경우에는 더욱 그렇습니다.
가장 큰 차이점은 특수 정적 정적 Java 클래스와 달리 싱글 톤이 여전히 일반적인 Java Bean이라는 것입니다. 그리고 이로 인해 더 많은 상황에서 싱글 톤이 허용됩니다. 실제로 기본 스프링 프레임 워크의 인스턴스화 전략입니다. 소비자는 단일 톤이 전달되고 있다는 것을 알거나 알 수 없으며 단지 일반 Java Bean처럼 취급합니다. Spring에서 자주 볼 수 있듯이 요구 사항이 변경되고 단일 항목이 프로토 타입이되어야하는 경우 소비자에 대한 코드 변경없이 완벽하게 수행 할 수 있습니다.
다른 누군가는 정적 클래스가 순전히 절차 적이어야한다고 언급했습니다 (예 : java.lang.Math). 내 마음에, 그런 클래스는 절대로 전달되어서는 안되며 정적 결승 이외의 속성을 보유해서는 안됩니다. 그 밖의 모든 것에는 싱글 톤을 사용하면 훨씬 유연하고 유지 관리가 쉽습니다.
백엔드에 연결하는 DB 프레임 워크가 있습니다. 여러 사용자에 대한 더티 읽기를 방지하기 위해 단일 인스턴스를 사용하여 언제든지 단일 인스턴스를 사용할 수 있습니다.
C #에서 정적 클래스는 인터페이스를 구현할 수 없습니다. 단일 인스턴스 클래스가 비즈니스 계약 또는 IoC 목적으로 인터페이스를 구현해야하는 경우 정적 클래스없이 Singleton 패턴을 사용합니다.
싱글 톤은 상태 비 저장 시나리오에서 상태를 유지하는 방법을 제공합니다
도움이 되길 바랍니다 ..
싱글 톤 클래스의 객체를 만들어 메소드에 전달할 수 있습니다.
싱글 톤 클래스는 상속을 제한하지 않습니다.
정적 클래스의 객체를 처분 할 수는 없지만 싱글 톤 클래스는 할 수 있습니다.
JDK에는 싱글 톤과 정적의 예가 있으며, 한편으로 java.lang.Math
는 정적 메소드가있는 최종 클래스입니다.java.lang.Runtime
으로는 싱글 톤 클래스입니다.
싱글 톤의 장점
정적 클래스에서 상태를 유지 관리하는 것이 버그, 특히 동시 환경에서 여러 스레드에 의한 적절한 병렬 병렬 수정없이 경쟁 조건으로 이어질 수 있기 때문에 싱글 톤 패턴보다 상태를 유지해야하는 것이 정적 클래스보다 더 나은 선택입니다.
단일 객체 클래스는 무거운 객체 인 경우 지연로드 될 수 있지만 정적 클래스에는 이러한 장점이 없으며 항상 열심히로드됩니다.
싱글 톤을 사용하면 상속 및 다형성을 사용하여 기본 클래스를 확장하고 인터페이스를 구현하며 다른 구현을 제공 할 수 있습니다.
Java의 정적 메소드는 대체 할 수 없으므로 융통성이 없습니다. 반면 싱글 톤 클래스에 정의 된 메소드를 확장하여이를 대체 할 수 있습니다.
정적 클래스의 단점
정적 클래스의 장점
그들 각각에 대한 자세한 설명은 너무 장황하므로 그냥 좋은 기사에 대한 링크를 넣어 -Singleton에 대해 알고 싶은 모든 것
단일 정적 클래스 인스턴스 (정적 또는 전역 변수가되는 클래스의 단일 인스턴스)와 단일 정적 포인터 간에는 큰 차이 가 있습니다. 힙의 클래스 인스턴스에 .
애플리케이션이 종료되면 정적 클래스 인스턴스의 소멸자가 호출됩니다. 즉, 정적 인스턴스를 싱글 톤으로 사용하면 싱글 톤이 제대로 작동하지 않습니다. 예를 들어 다른 스레드에서 해당 싱글 톤을 사용하는 코드가 여전히 실행중인 경우 해당 코드가 충돌 할 수 있습니다.
내 머리의 차이점은 객체 지향 프로그래밍 (Singleton / Prototype) 또는 기능적 프로그래밍 (Static)을 구현하는 것입니다.
우리가 집중해야 할 것이 결국 객체를 보유하고있을 때 싱글 톤 패턴으로 생성 된 객체의 수에 너무 집중하고 있습니다. 다른 사람들이 이미 말했듯이, 확장되고 매개 변수로 전달 될 수 있지만 가장 중요한 것은 상태가 가득 찼습니다.
반면에 static은 함수형 프로그래밍을 구현하는 데 사용됩니다. 정적 멤버는 클래스에 속합니다. 그들은 무국적자입니다.
그건 그렇고 당신은 싱글 톤 정적 클래스를 만들 수 있다는 것을 알고 있습니다 :)
getInstance()
(아마도 대부분의 경우 중요하지 않음 ).