Singleton (1)

 Creational Patterns ( 생성 패턴 )

These design patterns provides way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects need to be created for a given use case. 

생성패턴은 객체의 생성로직을 숨기고 new 명령어를 통하지 않고 객체를 생성하는 방법들을 제공한다. 이는 특정 상황에서 어떤 방법으로 객체를 생성해야할지를 결정하는데 있어서 유연성을 제공한다. 


 Structural Patterns ( 구조적 패턴 )

These design patterns concern class and object composition. Concept of inheritance is used to compose interfaces and define ways to compose objects to obtain new functionalities. 

구조적 패턴들은 클래스와 객체의 구성에 관여한다.

 

 Behavioral Patterns ( 행위적 패턴 )

These design patterns are specifically concerned with communication between objects.

이 패턴들은 객체들 사이의 커뮤니케이션에 관심을 가진다.

 

오늘 살펴볼  Singleton 패턴은 Creational 패턴에 속한다.  

 

Singleton Pattern Structure


 

패턴의 목적 ( Intent ) : 

Ensure a class only has one instance, and provide a global point of access to it.

프로그램상에서 단 하나의 인스턴스만을 요구하는 클래스를 만들 필요가 있어서 나온 패턴이다. global하게 access가능한 단 인스턴스 생성이 이 패턴의 목적이다. 

 

패턴이 나오게 된 동기 ( Motivation ) :

Application needs one, and only one, instance of an object. Additionally, lazy initialization and global access are necessary.

목적에서 말한 바와 같이 단 하나의 유일한 객체를 생성하고 이를 사용할 목적으로 나오게 된 패턴이다. 한번 생성하면 그 이후에는 생성된 객체를 이용만 할 뿐이다. 


유용성 ( Applicability ) :

Use the Singleton pattern when
· there must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.
· when the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code.

 

등장 인물 ( Participants ) :

· Singleton
o defines an Instance operation that lets clients access its unique instance. Instance is a class operation (that is, a class method in Smalltalk and a static member function in C++).
o may be responsible for creating its own unique instance.


원리 ( Collaborations ) :

· Clients access a Singleton instance solely through Singleton's Instance operation.

클라이언트들은 이 싱글턴객체에서 제공하는  getter메소드에 의해 오직 혼자만 접근한다.


패턴 사용의 장단점 ( Consequences ): 

The Singleton pattern has several benefits:
1. Controlled access to sole instance. Because the Singleton class encapsulates its sole instance, it can have strict control over how and when clients access it.
2. Reduced name space. The Singleton pattern is an improvement over global variables. It avoids polluting the name space with global variables that store sole instances.
3. Permits refinement of operations and representation. The Singleton class may be subclassed, and it's easy to configure an application with an instance of this extended class. You can configure the application with an instance of the class you need at run-time.
4. Permits a variable number of instances. The pattern makes it easy to change your mind and allow more than one instance of the Singleton class. Moreover, you can use the same approach to control the number of instances that the application uses. Only the operation that grants access to the Singleton instance needs to change.
5. More flexible than class operations. Another way to package a singleton's functionality is to use class operations (that is, static member functions in C++ or class methods in Smalltalk). But both of these language techniques make it hard to change a design to allow more than one instance of a class. Moreover, static member functions in C++ are never virtual, so subclasses can't override them polymorphically.

 

소스 예제 : 


1. 일반적인 경우 ( synchronizing할 필요가 없는 싱글턴 객체의 경우, 싱글쓰레드(single thread) )

 

// 싱글턴객체가 필요할 때는 인스턴스를 직접 만드는게 아니고 인스턴스를 달라고 요청을 하는 것이다.
public class Singleton {
  private static Singleton uniqueInstance;
 
  private Singleton() {}  // <---  생성자는 private -- 외부에서 new 를 사용하여 객체를 생성할 수 없다...
 
  public static Singleton getInstance() {  // 객체를 생성하는 static 메소드 하나
    if ( uniqueInstance == null ) {        // 이 부분은 객체를 처음 생성할 때만 필요하다~~
      uniqueInstance = new Singleton();
    }
    return uniqueInstance;
  }
}

2. 여러명이 동시접근할 수도 있는
싱글턴 객체의 경우 ( 멀티쓰레드, multi thread )

A. 위 코드의 문제점 )
public class Singleton {
  private static Singleton uniqueInstance;
 
  private Singleton() {}
 
  public static Singleton getInstance() {  
    if ( uniqueInstance == null ) {          // A Thread가 이 코드를 실행할 때
      uniqueInstance = new Singleton();      // B Thread가 객체 생성을 완료하지 않은 경우 
    }                                        // 두개의 객체가 생성될 수 있다.
 
    return uniqueInstance;
  }
}

B.Method synchronizing 으로 문제 해결 가능 

 

public class Singleton {
  private static Singleton uniqueInstance;
 
  private Singleton() {}

  // 메소드 자체에 synchronized 를 거는 방법 
  public static synchronized Singleton getInstance() {  
    if ( uniqueInstance == null ) {          
      uniqueInstance = new Singleton(); 
    }                                        
 
    return uniqueInstance;
  }
}

이 방법의 문제점 )
  • 이 방법은 성능에 영향을 끼칠 수 있다.
    ( 메소드를 동기화하면 성능이 100배 정도 저하된다고 책에 적혀있습니다. )
  • synchronized가 필요한 경우는 객체가 생성되는 처음 뿐이고 그 이후에는 쓸데없이 성능을 저하시키는 요인이다.

C. Double-checking Locking

public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() {} // 부분적으로 synchronized를 걸어 객체가 생성된 이후에는 synchronized 구문을 수행하지 않는다. public static Singleton getInstance() { if ( uniqueInstance == null ) { synchronized( Singleton.class ) { if ( uniqueInstance == null ) { uniqueInstance = new Singleton(); } } } return uniqueInstance; } }

관련 패턴들 : 

 Many patterns can be implemented using the Singleton pattern. See Abstract Factory, Builder, and Prototype.

 

추가 정보 :     

  • Abstract Factory, Builder, and Prototype can use Singleton in their implementation.
  • Facade objects are often Singletons because only one Facade object is required.
  • State objects are often Singletons.
  • The advantage of Singleton over global variables is that you are absolutely sure of the number of instances when you use Singleton, and, you can change your mind and manage any number of instances.
  • The Singleton design pattern is one of the most inappropriately used patterns. Singletons are intended to be used when a class must have exactly one instance, no more, no less. Designers frequently use Singletons in a misguided attempt to replace global variables. A Singleton is, for intents and purposes, a global variable. The Singleton does not do away with the global; it merely renames it.
    싱글턴 패턴은 가장 부적절하게 사용되는 패턴중 하나이다. 원래 싱글턴 패턴의 목적은 더도말고 덜도말고 오로지 단 하나의 인스턴스를 갖기 위함이었으나 일부 개발자들은 단순히 전역변수를 대체하기위해 사용할 때가 있다.
  • When is Singleton unnecessary? Short answer: most of the time. Long answer: when it's simpler to pass an object resource as a reference to the objects that need it, rather than letting objects access the resource globally. The real problem with Singletons is that they give you such a good excuse not to think carefully about the appropriate visibility of an object. Finding the right balance of exposure and protection for an object is critical for maintaining flexibility.
  • Our group had a bad habit of using global data, so I did a study group on Singleton. The next thing I know Singletons appeared everywhere and none of the problems related to global data went away. The answer to the global data question is not, "Make it a Singleton." The answer is, "Why in the hell are you using global data?" Changing the name doesn't change the problem. In fact, it may make it worse because it gives you the opportunity to say, "Well I'm not doing that, I'm doing this" – even though this and that are the same thing.

 

 

 

출처 :  http://sourcemaking.com/design_patterns/singleton

Design Patterns : Element of Reusable Object Oriented Software ( by GoF, 1994 ) 

http://www.javajigi.net/display/SWD/ch05_singletonpattern