Design (5)

 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

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.

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

 

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

 

Prototype Pattern Structure



패턴의 목적 ( Intent ) : 

- Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. 

하나의 프로토타입 인스턴스를 만들고 필요할때마다 프로토타입 인스턴스를 복사해서 객체를 생성하기 위함 

- Co-opt one instance of a class for use as a breeder of all future instances. 

- The new operator considered harmful.

new 키워드를 이용하는 것이 안좋은 상황일 때 프로토타입 패턴을 이용하자. 

 

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

 

객체 생성 비용이 비싼경우 프로토타입 원형을 만들고 클로닝 기법을 이용해서 객체를 쉽게 생성하고자 하기 위함.


유용성 ( Applicability ) :

Use the Prototype pattern when a system should be independent of how its products are created, composed, and represented; and
· when the classes to instantiate are specified at run-time, for example, by dynamic loading; or

클래스의 동적로딩이 필요할 때
· to avoid building a class hierarchy of factories that parallels the class hierarchy of products; or

제품의 클래스 계층과 동일한 팩토리 클래스 계층을 만들고 싶지 않을 때
· when instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state.

 

등장 인물 ( Participants ) :

· Prototype
o declares an interface for cloning itself.
· ConcretePrototype
o implements an operation for cloning itself.
· Client
o creates a new object by asking a prototype to clone itself. 


원리 ( Collaborations ) :

· A client asks a prototype to clone itself.


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

Prototype has many of the same consequences that Abstract Factory and Builder have: It hides the concrete product classes from the client, thereby reducing the number of names clients know about. Moreover, these patterns let a client work with application-specific classes without modification.


Additional benefits of the Prototype pattern are listed below.


1. Adding and removing products at run-time. Prototypes let you incorporate a new concrete product class into a system simply by registering a prototypical instance with the client. That's a bit more flexible than other creational patterns, because a client can install and remove prototypes at run-time.


2. Specifying new objects by varying values. Highly dynamic systems let you define new behavior through object composition—by specifying values for an object's variables, for example—and not by defining new classes. You effectively define new kinds of objects by instantiating existing classes and registering the instances as prototypes of client objects. A client can exhibit new behavior by delegating responsibility to the prototype. This kind of design lets users define new "classes" without programming. In fact, cloning a prototype is similar to instantiating a class. The Prototype pattern can greatly reduce the number of classes a system needs. In our music editor, one GraphicTool class can create a limitless variety of music objects.


3. Specifying new objects by varying structure. Many applications build objects from parts and subparts. Editors for circuit design, for example, build circuits out of subcircuits.1 For convenience, such applications often let you instantiate complex, user-defined structures, say, to use a specific subcircuit again and again. The Prototype pattern supports this as well. We simply add this subcircuit as a prototype to the palette of available circuit elements. As long as the composite circuit object implements Clone as a deep copy, circuits with different structures can be prototypes.  

 

4. Reduced subclassing. Factory Method often produces a hierarchy of Creator classes that parallels the product class hierarchy. The Prototype pattern lets you clone a prototype instead of asking a factory method to make a new object. Hence you don't need a Creator class hierarchy at all. This benefit applies primarily to languages like C++ that don't treat classes as first-class objects. Languages that do, like Smalltalk and Objective C, derive less benefit, since you can always use a class object as a creator. Class objects already act like prototypes in these languages.


5. Configuring an application with classes dynamically. Some run-time environments let you load classes into an application dynamically. The Prototype pattern is the key to exploiting such facilities in a language like C++. An application that wants to create instances of a dynamically loaded class won't be able to reference its constructor statically. Instead, the run-time environment creates an instance of each class automatically when it's loaded, and it registers the instance with a prototype manager (see the
Implementation section). Then the application can ask the prototype manager for instances of newly loaded classes, classes that weren't linked with the program originally. The ET++ application framework [WGM88] has a run-time system that uses this scheme.
The main liability of the Prototype pattern is that each subclass of Prototype must implement the Clone operation, which may be difficult. For example, adding Clone is difficult when the classes under consideration already exist. Implementing Clone can be difficult when their internals include objects that don't support copying or have circular references.

 

관련 패턴들 : 

 Prototype and Abstract Factory are competing patterns in some ways, as we discuss at the end of this chapter. They can also be used together, however. An Abstract Factory might store a set of prototypes from which to clone and return product objects.
Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.

 

추가 정보 :     

  • Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used properly. At other times they are complementory: Abstract Factory might store a set of Prototypes from which to clone and return product objects. Abstract Factory, Builder, and Prototype can use Singleton in their implementations.
  • Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype.
  • Factory Method: creation through inheritance. Protoype: creation through delegation.
  • Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Protoype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.
  • Prototype doesn't require subclassing, but it does require an "initialize" operation. Factory Method requires subclassing, but doesn't require Initialize.
  • Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.
  • Prototype co-opts one instance of a class for use as a breeder of all future instances.
  • Prototypes are useful when object initialization is expensive, and you anticipate few variations on the initialization parameters. In this context, Prototype can avoid expensive "creation from scratch", and support cheap cloning of a pre-initialized prototype.
  • Prototype is unique among the other creational patterns in that it doesn't require a class – only an object. Object-oriented languages like Self and Omega that do away with classes completely rely on prototypes for creating new objects.

 

 

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

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

 


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.

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

 

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

 

Abstract Factory Pattern Structure


패턴의 목적 ( Intent ) : 

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

추상 팩토리 패턴은 구상클래스를 명시하지 않아도 연관있거나 의존적인 객체의 그룹을 생성하기위한 인터페이스를 제공하는 패턴이다.

참고로 Factory는 싱글턴 패턴을 사용하는 것이 일반적이다. ( 동일한 제품을 생산하는 두개의 다른 공장을 하나의 애플리케이션에서 가지고 있을 필요는 없기 때문이다. ) 

 

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



 GOF의 디자인 패턴에서 예로 든 내용을 좀 꾸며서 얘기해보겠다.  

자, 우리 회사는 여러개의 위젯을 제공하는데 위젯마다 Look and Feel ( 이하 LNF )이 다르다. 지금까지 Window와 ScrollBar를 내가 만들어 놨는데 신입개발자가 이를 이용해서 위젯을 만들 수 있도록 해주고 싶다. 그래서 나는 WidgetFactory를 만들어 신입개발자가 사용할 수 있도록 할 것이다. 내가 만든 Window와 ScrollBar의 구상 클래스를 몰라도 WidgetFactory에서 알아서 생성해 줄 테니 신입개발자는 WidgetFactory 사용법만 알면 되겠지. 신입개발자가 PMWidget을 만들고 싶으면 PMWidgetFactory를 이용하면되고 MotifWidget을 만들고 싶으면 MotifWidgetFactory를 사용하면 되는거다. 


유용성 ( Applicability ) :

Use the Abstract Factory pattern when


· a system should be independent of how its products are created, composed, and represented.
· a system should be configured with one of multiple families of products.  

· a family of related product objects is designed to be used together, and you need to enforce this constraint.
· you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations.

 

등장 인물 ( Participants ) :

· AbstractFactory (WidgetFactory)
o declares an interface for operations that create abstract product objects.
· ConcreteFactory (MotifWidgetFactory, PMWidgetFactory)
o implements the operations to create concrete product objects.
· AbstractProduct (Window, ScrollBar)
o declares an interface for a type of product object.
· ConcreteProduct (MotifWindow, MotifScrollBar)
o defines a product object to be created by the corresponding concrete factory.
o implements the AbstractProduct interface.
· Client
o uses only interfaces declared by AbstractFactory and AbstractProduct classes.


원리 ( Collaborations ) :

· Normally a single instance of a ConcreteFactory class is created at run-time.
This concrete factory creates product objects having a particular implementation. To create different product objects, clients should use a different concrete factory.
· AbstractFactory defers creation of product objects to its ConcreteFactory subclass.

 



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

The Abstract Factory pattern has the following benefits and liabilities:


1. It isolates concrete classes. The Abstract Factory pattern helps you control the classes of objects that an application creates. Because a factory encapsulates the responsibility and the process of creating product objects, it isolates clients from implementation classes. Clients manipulate instances through their abstract interfaces. Product class names are isolated in the implementation of the concrete factory; they do not appear in client code.  

 

2. It makes exchanging product families easy. The class of a concrete factory appears only once in an application—that is, where it's instantiated. This makes it easy to change the concrete factory an application uses. It can use different product configurations simply by changing the concrete factory. Because an abstract factory creates a complete family of products, the whole product family changes at once. In our user interface example, we can switch from Motif widgets to Presentation Manager widgets simply by switching the corresponding factory objects and recreating the interface.


3. It promotes consistency among products. When product objects in a family are designed to work together, it's important that an application use objects from only one family at a time. AbstractFactory makes this easy to enforce.


4. Supporting new kinds of products is difficult. Extending abstract factories to produce new kinds of Products isn't easy. That's because the AbstractFactory interface fixes the set of products that can be created. Supporting new kinds of products requires extending the factory interface, which involves changing the AbstractFactory class and all of its subclasses

새 로운 종류의 제품을 생산하는 것이 힘들다. 새로운 제품을 만들기 위해 AbstractFactory가 변경이 되면 이를 구현하는 구상클래스(concrete classes)들이 모두 변경되야 하기 때문이다. 이런 문제를 보완하기 위해서 Prototype-based Factory ( 프로토타입 패턴을 이용한 Factory )를 이용하는 방법도 있다.  

 

 

 

관련 패턴들 : 

 AbstractFactory classes are often implemented with factory methods (Factory Method), but they can also be implemented using Prototype.
A concrete factory is often a singleton.

 

추가 정보 :     

  • Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used profitably. At other times they are complementary: Abstract Factory might store a set of Prototypes from which to clone and return product objects, Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementation.
  • Abstract Factory, Builder, and Prototype define a factory object that's responsible for knowing and creating the class of product objects, and make it a parameter of the system. Abstract Factory has the factory object producing objects of several classes. Builder has the factory object building a complex product incrementally using a correspondingly complex protocol. Prototype has the factory object (aka prototype) building a product by copying a prototype object.
  • Abstract Factory classes are often implemented with Factory Methods, but they can also be implemented using Prototype.
  • Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.
  • Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.
  • Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

 

 

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

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


 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.

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

 

오늘 살펴볼 Template Method 패턴은 Behavioral 패턴에 속한다.  

 

템 플릿하면 뭐가 떠오르는가? 사전적 의미는 형판, 견본이다. 우리가 일상적으로 쓸 때 템플릿이라 하면 뭔가의 기본구조(?)라고 생각을 할 수 있을 것이다. 이 템플릿 메소드는 바로 그런 형판, 견본, 기본구조의 역할을 하는 메소드이다. 그리고 이런 메소드를 이용하는 패턴을 템플릿 메소드 패턴이라고 이해하면 된다. 자 아래 그림을 살펴보자.

 


 

 

위 그림은 소방관, 목수, 우체부, 관리자 등 다양한 직업의 사람들을 객체로 만들었다. 이 사람들은 공통적으로 일하는 사람들이므로 Worker라는 클래스의 하위로 만들었고 모든 사람들은 동일한 일과 순서가 있다. 이 일과 순서는 DailyRoutine()내에 정의되어있고 Worker 클래스를 이용하는 클라이언트에서는 DailyRoutine()만 호출한다. 그러면 이 Worker가 소방관이냐, 우체부냐에 따라 work()에서 하는 일이 달라진다. 위 그림에서보면 모든 사람들이 work()를 오버라이드해서 재정의하고있기 때문이다. 여기서 DailyRoutine() 메소드가 템플릿 메소드가 되는 것이고 이런 식의 패턴을 템플릿 메소드 패턴이라 하는 것이다. 

 

Template Method Pattern Structure

 


 


패턴의 목적 ( Intent ) :
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.


어떤 작업을 수행하는 알고리즘의 뼈대를 정의하고 과정은 하위클래스가 정의하게끔 한다. 템플릿 메소드는 하위클래스들이 알고리즘의 구조에 변화를 주지 않는 선에서 알고리즘 내의 특정 과정만 재정의 할 수 있게끔 해준다.

 

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



 워 드 프로세서를 예를들어 설명하자면 Document(문서)파일과 Application(워드프로세서)가 있는데 이 워드프로세서가 문서를 열어본다는 시나리오를 생각해보자. OpenDocument()는 문서가 열수 있는 문서인지(읽어들일 수 있는지) 검사를 할 것이고, 워드프로세서내에서 정의한 Document객체를 생성하고 파일로부터 문서를 읽어들여 객체에 저장할 것이다.  

We call OpenDocument a template method. A template method defines an algorithm in terms of abstract operations that subclasses override to provide concrete behavior. Application subclasses define the steps of the algorithm that check if the document can be opened (CanOpenDocument) and that create the Document (DoCreateDocument). Document classes define the step that reads the document (DoRead). The template method also defines an operation that lets Application subclasses know when the document is about to be opened (AboutToOpenDocument), in case they care.  

By defining some of the steps of an algorithm using abstract operations, the template method fixes their ordering, but it lets Application and Document subclasses vary those steps to suit their needs.

 

여기서 이 OpenDocument()는 하나의 템플릿 메소드이다. 템플릿 메소드는 말그대로 특정 동작을 하기위한 골격만 제공한다. 골격내부의 구성은 하위클래스들이 하도록 하는 것이다. 

 

 

유용성 ( Applicability ) :

The Template Method pattern should be used

· to implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary.

템플릿 메소드 패턴은 변하지 않을 알고리즘의 구조만 정의하고 구체적인 구현은 하위클래스들에게 위임하고자 할 때 사용한다. 

 

· when common behavior among subclasses should be factored and localized in a common class to avoid code duplication. This is a good example of"refactoring to generalize" as described by Opdyke and Johnson.

You first identify the differences in the existing code and then separate the differences into new operations. Finally, you replace the differing code with a template method that calls one of these new operations.

템플릿 메소드 패턴은 여러 하위 클래스들 중에서 중복된 부분을 제거하기 위해서도 사용될 수 있다.


· to control subclasses extensions. You can define a template method that calls "hook" operations (see Consequences) at specific points, thereby permitting extensions only at those points.

템플릿 메소드 패턴은 하위 클래스들의 확장을 컨트롤하고자 할 때 이용할 수도 있다. 우리는 템플릿 메소드에 특정시점에 hook를 호출하도록 정의하여 그 특정 시점에만 확장을 허용하도록 할 수도 있다. ( 무슨 말인지 모르겠다. 아래쪽에 Consequences에서 hook가 뭔지 더 알아보자 ) 

 

 

등장 인물 ( Participants ) :
· AbstractClass (Application)
o defines abstract primitive operations that concrete subclasses define to implement steps of an algorithm.
o implements a template method defining the skeleton of an algorithm.The template method calls primitive operations as well as operationsdefined in AbstractClass or those of other objects.
· ConcreteClass (MyApplication)
o implements the primitive operations to carry out subclass-specific steps of the algorithm.

 

원리 ( Collaborations ) :

ConcreteClass relies on AbstractClass to implement the invariant steps of the algorithm.


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

Template methods are a fundamental technique for code reuse. They are particularly important in class libraries, because they are the means for factoring out common behavior in library classes.
Template methods lead to an inverted control structure that's sometimes referred to as "the Hollywood principle," that is, "Don't call us, we'll call you" .
This refers to how a parent class calls the operations of a subclass and not the other way around.

Template methods call the following kinds of operations:
· concrete operations (either on the ConcreteClass or onclient classes);
· concrete AbstractClass operations (i.e., operations that are generally useful to subclasses);
· primitive operations (i.e., abstract operations);
· factory methods (see Factory Method); and
· hook operations, which provide default behavior that subclasses can extend if necessary. A hook operation often doesnothing by default. It's important for template methods to specify which operations arehooks (may be overridden) and which are abstract operations(must be  overridden). To reuse an abstract class effectively,subclass writers must understand which operations are designed foroverriding.
A subclass can extend a parent class operation's behavior byoverriding the operation and calling the parent operation explicitly:


void DerivedClass::Operation () {
// DerivedClass extended behavior
ParentClass::Operation();
}

 

Unfortunately, it's easy to forget to call the inherited operation.We can transform such an operation into a template method to give the parent control over how subclasses extend it. The idea is to call a hook operation from a template method in the parent class.Then subclasses can then override this hook operation:


void ParentClass::Operation () {
// ParentClass behavior
HookOperation();
}


HookOperation does nothing in ParentClass:


void ParentClass::HookOperation () { }


Subclasses override HookOperation to extend its behavior:


void DerivedClass::HookOperation () {
// derived class extension
}


관련 패턴들 : 

Factory Methods are often called by template methods. In the Motivation example, the factory method DoCreateDocument is called by the template method OpenDocument.
Strategy : Template methods use inheritance to vary part of an algorithm. Strategies use delegation to vary the entire algorithm.

 

추가 정보 :     

  • Strategy is like Template Method except in its granularity.
  • Template Method uses inheritance to vary part of an algorithm. Strategy uses delegation to vary the entire algorithm.
  • Strategy modifies the logic of individual objects. Template Method modifies the logic of an entire class.
  • Factory Method is a specialization of Template Method.

 

 

 

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

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


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.

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

 

오늘 살펴볼 State 패턴은 Behavioral 패턴에 속한다. 

 

State Pattern Structure

 

패턴의 목적 ( Intent ) : 

Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.

State 패턴의 목적은 내부 상태의 변화에 따라 객체의 행위를 변경할 수 있도록 하기 위함이다.


 위 다이어그램을 예제로 들면 TCPConnection은 TCPState객체를 가지고 있는 클래스다. 그리고 이 TCPState객체는 상태를 나타내는 클래스로 크게 세가지 상태로 나뉘는데 ( Established, Listen, Closed ) 이 상태의 변화에 따라 TCPConnection에서 호출하는 open()메소드가 TCPEstablished객체의 open()이 될 수도 있고 TCPListen나  TCPClosed 객체의 open()이 될 수도 있다.  

 

유용성 ( Applicability ) :

· An object's behavior depends on its state, and it must change its behavior at run-time depending on that state.

객체의 행위가 상태에 따라 동적으로 변해야 할 때
· Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a
separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects.

어떤 작업이 객체의 상태에 의존하는 여러개의 큰 조건문을 가지고 있다고 해보자( 쉽게 말해 객체의 상태를 나타내는 상수값이 조건문의 조건절에 들어가 있다고 생각해보자 ). 일반적으로 상태라는 것은 최소 하나 이상의 상수값에 의해 표현이 될 수 있는데, 이를 상태패턴을 이용하여 클래스에 담아버리는 것이다. 즉, 객체의 상태값을 나타내는 객체를 만들어 버리는 것이다.

 

등장 인물 :
· Context (TCPConnection)
o defines the interface of interest to clients.
o maintains an instance of a Concrete State subclass that defines the current state.

· State (TCPState)
o defines an interface for encapsulating the behavior associated with a particular state of the Context. 

 

· ConcreteState subclasses (TCPEstablished, TCPListen, TCPClosed)
o each subclass implements a behavior associated with a state of the Context.

 

원리 ( Collaborations ) :

· Context delegates state-specific requests to the current ConcreteState object.

Context는 상태에 따른 메소드 호출을 ConcreteState객체에 위임한다.
· A context may pass itself as an argument to the State object handling the request. This lets the State object access the context if necessary.

상태객체가 Context를 필요로한다면 Context객체는 자신을 argument로 넘겨주어 상태객체에서 접근할 수 있도록 할 수 있다.
· Context is the primary interface for clients. Clients can configure a context with State objects. Once a context is configured, its clients don't have to deal with the State objects directly.

클라이언트는 상태객체를 이용해서 context를 설정할 수 있는데 한번 설정하면 그 다음부터는 상태객체에 직접적으로 접근할 필요가 없다.
· Either Context or the ConcreteState subclasses can decide which state succeeds another and under what circumstances.

Context 또는 ConcreteState의 하위 클래스들은 상태의 순서를 결정할 수 있다.


패턴 사용의 장단점 ( Consequences ):
1. It localizes state-specific behavior and partitions behavior for different states.The State pattern puts all behavior associated with a particular state into one object. Because all state-specific code lives in a State subclass, new states and transitions can be added easily by defining new subclasses.
An alternative is to use data values to define internal states and have Context operations check the data explicitly. But then we'd have look-alike conditional or case statements scattered throughout Context's implementation. Adding a new state could require changing several operations, which complicates maintenance.

The State pattern avoids this problem but might introduce another, because the pattern distributes behavior for different states across several State subclasses. This increases the number of classes and is less compact than a single class. But such distribution is actually good if there are many states, which would otherwise necessitate large conditional statements.
Like long procedures, large conditional statements are undesirable.They're monolithic and tend to make the code less explicit, which in turn makes them difficult to modify and extend. The State pattern offers a better way to structure state-specific code. The logic that determines the state transitions doesn't reside in monolithic if or switch statements but instead is partitioned between the State  subclasses. Encapsulating each state transition and action in a class elevates the idea of an execution state to full object status. That imposes structure on the code and makes its intent clearer. 

 

2. It makes state transitions explicit.When an object defines its current state solely in terms of internal data values, its state transitions have no explicit representation;they only show up as assignments to some variables. Introducing separate objects for different states makes the transitions more explicit. Also, State objects can protect the Context from inconsistent internal states, because state transitions are atomic from the Context's perspective—they happen by rebinding one variable (the Context's State object variable), not several. 

 

3. State objects can be shared.If State objects have no instance variables—that is, the state they represent is encoded entirely in their type—then contexts can sharea State object. When states are shared in this way, they are essentially flyweights (see Flyweight) with nointrinsic state, only behavior.


관련 패턴들 : 

The Flyweight pattern explains when and how State objects can be shared.

Flyweight 패턴은 언제 어떻게 상태 객체들이 공유되는지 설명해준다.

State objects are often Singletons.

상태 객체들은 대부분 싱글턴이다.



추가 정보 :

  • State objects are often Singletons.
  • Flyweight explains when and how State objects can be shared.
  • Interpreter can use State to define parsing contexts.
  • Strategy has 2 different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic).
  • The structure of State and Bridge are identical (except that Bridge admits hierarchies of envelope classes, whereas State allows only one). The two patterns use the same structure to solve different problems: State allows an object's behavior to change along with its state, while Bridge's intent is to decouple an abstraction from its implementation so that the two can vary independently.
  • The implementation of the State pattern builds on the Strategy pattern. The difference between State and Strategy is in the intent. With Strategy, the choice of algorithm is fairly stable. With State, a change in the state of the "context" object causes it to select from its "palette" of Strategy objects.

 

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

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