Posted by: pegasuskim | May 3, 2008

Singleton

원본출처 : http://home.earthlink.net/~huston2/dp/singleton.html

Singleton

Intent

  • Ensure a class has only one instance, and provide a global point of access to it. [GoF, p127]

          ( 클래스가 오직 하나의 인스턴스를 가지도록한다. 그리고 그것에 접근할 수 있는 전역 포인트를 제공한다. )

  • Encapsulated “just-in-time initialization” or “initialization on first use”.

          ( just-in-time 초기화 or 최초사용시 초기화 를 캡슐화 한다. )

Problem

Application needs one, and only one, instance of an object.
( 어플리케이션이 어떤 객체에 대해서 오직 하나의 인스턴스만을 필요로 한다 )

Additionally, lazy initialization and global access are necessary.
( 게다가 초기화 작업은 지루하고, 전역적인 액세스가 필요하다. )

 

Structure Summary

Structure category:   miscellaneous
Similar patterns:   Abstract Factory   Flyweight   Template Method
( 보이는것처럼 클라이언트는 자신만의 인스턴스를 만들 수는 없지만. 클래스 자체적으로 제공하는 싱글 인스턴스를 사용해야 한다. )

Discussion

Make the class of the single instance object responsible for creation, initialization, access, and enforcement.
( 생성, 초기화, 액세스, 권한? 의 책임을 지는 싱글 인스턴스 객체의 클래스를 만들어라. )
Declare the instance as a private static data member.
( 인스턴스를 private static 데이터 멤버로 선언해라. )
Provide a public static member function that encapsulates all initialization code, and provides access to the instance.

( 인스턴스에 접근을 제공하고 초기화 하는 기능을 캡슐화하여 public static 멤버 함수로 제공해라 .)
The client calls the accessor function (using the class name and scope resolution operator) whenever a reference to the single instance is required.

( 언제든지 싱글 인스턴스가 필요하면 클라이언트는 accessor fuction( 클레스 네임과 scope resolution operator을 사용하는 ) 을 호출한다. )

Singleton should be considered only if all three of the following criteria are satisfied:
( 다음 세가지 범주가 모두 만족하는 상황에서만 싱글톤의 사용을 고려 해야 한다. )

  • Ownership of the single instance cannot be reasonably assigned
  • ( 싱글 인스턴스의 소유권이 특정 대상에게 부여될 수 없다. )
  • Lazy initialization is desirable
  • ( 초기화가 끔찍하게 지루하다.  )
  • Global access is not otherwise provided for
  • ( 전역적인 액세스 이외의 다른거는 제공되어서는 안된다. )

If ownership of the single instance, when and how initialization occurs, and global access are not issues, Singleton is not sufficiently interesting.
( 만약 싱글 인스턴스의 소유권 어쩌구?, 초기화 어쩌구?, 글로벌 액세스 필요 없다면, 싱글톤의 사용은 고려할만한 대상이 아니다. )

The Singleton pattern can be extended to support access to an application-specific number of instances.

( 싱글톤 패턴은 어플리케이션에 따라 몇개의 인스턴스를 가지는 버전으로 확장될 수 있다. )

The “static member function accessor” approach will not support subclassing of the Singleton class.
( static 멤버 함수로 구현된 accessor 접근방식은 싱글톤을 상속받은 클래스에서는 사용할 수 없다. )

If subclassing is desired, refer to the discussion in the book.

( 상속이 필요하면, 책을보라?  )

Deleting a Singleton class/instance is a non-trivial design problem.
( 싱글톤 클래스/인스턴스를 삭제하는 문제는 사소한지 않은 디자인 문제다.  )

See “To kill a Singleton” by John Vlissides (C++ Report, Jun 96, pp10-19) for a discussion.
( “To kill a Singleton” 문서를 봐라. )

Structure

Make the class of the single instance responsible for access and “initialization on first use”.
( access 와 “initialization on first use” 할 책임이 있는 싱글톤 클래스를 만들어라. )

The single instance is a private static attribute. The accessor function is a public static method.
( 싱글 인스턴스는 private static attribute. 이고   accessor function 은 public static method 이다. )

Example

The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance.
( 싱글톤 패턴은 클래스의 인스턴스가 오직 하나만 존재한다는것을 보장하고 . 그에 대한 전역 액세스 포인트를 제공해 준다. )
It is named after the singleton set, which is defined to be a set containing one element.
( 이것은 하나의 원소를 가지는 집합인 singleton set의 이름을 따서 명명되었다.  )
The office of the President of the United States is a Singleton.
( 쌀나라의 대통령의 사무실은 싱글톤이다. )
The United States Constitution specifies the means by which a president is elected, limits the term of office, and defines the order of succession.
( )
As a result, there can be at most one active president at any given time.
( )
Regardless of the personal identity of the active president, the title, “The President of the United States” is a global point of access that identifies the person in the office.
( )
[Michael Duell, "Non-software examples of software design patterns", Object Magazine, Jul 97, p54]

example–>

Check list

  1. Define a private static attribute in the “single instance” class.
  2. Define a public static accessor function in the class.
  3. Do “lazy initialization” (creation on first use) in the accessor function.
  4. Define all constructors to be protected or private.
  5. Clients may only use the accessor function to manipulate the Singleton.

( 1. ”single instance” 클래스에 private static 데이터멤버를 선언한다.  )
( 2. 클래스에 public static 함수를 accessor 로서 선언한다. )
( 3. 지루한 초기화 작업을 accessor에서 해준다. ) creation on first use
( 4. 모든 생성자를 protected나 private로 선언한다. )
( 5. 클라이언트는 싱글톤을 조작하기 위해서는 accessor 함수만을 이용해야 한다. )

Before and after

 // Make the class responsible for its own
// global pointer and “initialization on
// first use” (by using a private static
// pointer and a public static accessor
// method).  The client uses only the public
// accessor method.

class GlobalClass {
   int    m_value;
   static GlobalClass* s_instance;
   GlobalClass( int v=0 ) { m_value = v; }
public:
   int  get_value()        { return m_value; }
   void set_value( int v ) { m_value = v; }
   static GlobalClass* instance() {
      if ( ! s_instance )
         s_instance = new GlobalClass;
      return s_instance;
   }
};

// Allocating and initializing GlobalClass’s
// static data member.  The pointer is being
// allocated – not the object inself.
GlobalClass* GlobalClass::s_instance = 0;

void foo( void ) {
   GlobalClass::instance()->set_value( 1 );
   cout << “foo: global_ptr is “
        << GlobalClass::instance()->get_value()
        << ‘\n’;
}

void bar( void ) {
   GlobalClass::instance()->set_value( 2 );
   cout << “bar: global_ptr is “
        << GlobalClass::instance()->get_value()
        << ‘\n’;
}

int main( void ) {
   cout << “main: global_ptr is “
        << GlobalClass::instance()->get_value()
        << ‘\n’;
   foo();
   bar();
}

// main: global_ptr is 0
// foo: global_ptr is 1
// bar: global_ptr is 2

 

Rules of thumb

Abstract Factory, Builder, and Prototype can use Singleton in their implementation. [GoF, p134]

Facade objects are often Singletons because only one Facade object is required. [GoF, p193]

State objects are often Singletons. [GoF, p313]

It’s relatively easy to protect Singleton against multiple instantiations because there is good language support in this area. The most complicated problem is managing a Singleton’s lifetime, especially its destruction … There are serious threading issues surrounding the pattern. [Alexandrescu, p155]   For C++ lifetime issues, see Alexandrescu, pp133-145.   For C++ multi-threaded implementation, see Alexandrescu, pp145-148.   For Java multi-threaded implementation, see Freeman, pp179-182.   For subclassing the Singleton instance, see Gamma, pp130-131.

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. [Ralph Johnson]

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. [Hyslop, p51]

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. [Kerievsky, pp115-116]

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. [Frieder Knauss]

 


Leave a response

Your response:

Categories