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