싱글턴 패턴 :: Singleton Pattern

설계 패턴은 소프트웨어 설계에서 상에서의 공통 문제에 대한 일반적인 솔루션이라 할 수 있는데, 그 기본 개념은 솔루션을 코드로 변환하면 그 코드를 다양한 문제 상황에 적용할 수 있다는 것이다. 설계 패턴에 관한 논의는 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 등이 공동 집필한 Design Patterns: Elements of Reusable Object-Oriented Software에서 시작되었다. 이 책에서는 패턴을 생성, 구조, 동작의 세 가지 주요 영역이 포함하여 다양한 주제 영역으로 분류하고 있다. 생성 패턴(Creational patterns)은 객체가 생성되는(객체 지향 용어로는 ‘예시되는(instantiated)’) 방식을 기술한다. 구조 패턴(Structural patterns)은 객체들을 연결하고 결합하는 방식을 도와주고, 동작 패턴(Behavioral patterns)은 알고리즘 또는 통신 메커니즘을 기술한다. 몇 가지 공통 패턴의 이름으로는 생성 영역의 Singleton, 동작 영역의 Observer, 구조 영역 Facade를 들 수 있다. 본 테크 팁에서는 자바 프로그래밍 언어의 맥락에서 Singleton 패턴을 면밀히 살펴보도록 한다.

Singleton 패턴은 흔히 사용되는 생성 패턴의 하나이다. 이는 하나의 클래스에서 오직 하나의 인스턴스만 생성되도록 보장하는 기법을 기술한다. 이는 본질적으로, 클래스 외부의 누구도 객체의 인스턴스를 생성하지 못하게 하는 접근법을 사용한다. 일반적으로 Singleton은 느리게 생성되어 필요 시점까지 메모리의 요구를 줄여준다. 이 접근법은 다양한 방식으로 구현이 가능하다.

생성되고 있는 하나의 인스턴스가 서브클래스가 되리라는 것을 알고 있다면, 상위(parant) 클래스를 추상화하고 메소드를 제공하여 현재의 인스턴스를 얻도록 한다. 그 일례로 AWT 패키지의 Toolkit 클래스를 들 수 있으며, Toolkit을 위한 생성자는 public(이 특정 경우에는 디폴트 생성자)이다.
   public Toolkit()
그리고 클래스는 특정 서브클래스(이 경우에는 플랫폼을 따름)를 얻기 위한 getDefaultToolkit() 메소드를 가진다.
   public static Toolkit getDefaultToolkit()
썬 자바 런타임을 탑재한 Linux 플랫폼 상에서 특정 서브클래스는 sun.awt.X11.XToolkit 타입이다. 하지만 사용자는 공통 추상 상위 클래스인 Toolkit을 통해 클래스에 액세스할 뿐이므로 이 부분까지 알아야 할 필요는 없다.

Collator 클래스는 이 패턴의 또 다른 예로, 약간의 차이가 있다. 이 클래스는 2개의 getInstance() 메소드를 제공하고, 무인자(no-argument) 버전은 디폴트 locale을 위한 Collator를 얻는다. 이 때, 사용자는 자체 locale을 전달하여 해당 locale을 위한 Collator 인스턴스를 얻을 수 있다. 동일 locale에 대한 Collator를 여러 차례 요청해도 동일한 Collator 인스턴스를 돌려받게 되며, 생성자 자체는 보호된다. 한편, J2SE 표준 라이브러리 전반에 걸쳐 클래서 생성을 제한하는 유사한 방식을 발견할 수 있다.

이 시점에서 클래스 생성자에 대한 액세스를 제한하면 자동적으로 Singleton이 된다고 생각할 수도 있겠으나, 그렇지 않다. 문제가 되는 케이스는 Calendar 클래스인데, Calendar 클래스 생성자는 보호되며, 이 클래스는 클래스 인스턴스를 얻기 위한 getInstance() 메소드를 제공한다. 그러나 getInstance() 메소드를 호출할 때마다 새로운 클래스 인스턴스가 얻어짐으로 결국 이는 Singleton이 아닌 것이다.

사용자의 자체 Singleton 클래스 생성 시에는 오직 하나의 인스턴스만 생성되도록 유의해야 한다.
   public class MySingleton {
     private static final MySingleton INSTANCE = 
       new MySingleton();

     private MySingleton() {
     }

     public static final MySingleton getInstance() {
       return INSTANCE;
     }
   }
정적 메소드 getInstance()는 단일 클래스 인스턴스를 리턴한다. 단일 인스턴스가 서브클래스일 필요가 있더라도 API를 변경할 필요는 없다는 점에 주목할 것.

이론적으로는 INSTANCE 변수가 public일 수 있으므로 getInstance() 메소드는 필요치 않으나 getInstance() 메소드는 향후에 시스템을 변경할 경우 유연성을 제공한다. 바람직한 가상 머신 구현이라면 정적 getInstance() 메소드에 대한 호출을 즉시 처리(inline)해야 한다.

Singleton 생성 작업은 이것으로 그치지 않는다. 즉, Singleton 클래스를 Serializable로 만들 필요가 있다면 반드시 readResolve() 메소드를 제공해야 한다.
  /**
   * Ensure Singleton class
   */
  private Object readResolve() throws ObjectStreamException {
    return INSTANCE;
  }
readResolve() 메소드가 갖추어진 상태에서 deserialization은 단일(오직 하나의) 객체(getInstance() 메소드에 대한 호출에 의해 생성되는 것과 동일한 객체이다)로 귀결되는데, 사용자가 readResolve() 메소드를 제공하지 않을 경우에는 객체를 deserialize할 때마다 객체 인스턴스가 생성된다.

Singleton 패턴은 오직 단일한 리소스만 가지고 있고 그 단일 리소스의 상태 정보에 대한 액세스를 공유할 필요가 있음을 알고 있을 경우에 유용하다. 설계 시에 Singleton 패턴의 필요성을 파악하면 개발을 간소화할 수 있다. 하지만, 때로는 성능 문제로 코드를 refactor하고 나중에 패턴을 사용하게 되기까지 필요성을 인식하지 못하는 수가 있다. 예를 들어, 프로그램이 동일한 클래스의 인스턴스를 반복 생성하여 상태 정보와 함께 전달하기 때문에 시스템 성능이 저하되는 경우가 발생할 수 있다. Singleton 패턴으로 변경하면 동일한 객체가 반복되는 것을 방지할 수 있는데, 이는 시스템이 객체를 재생성하는데 드는 시간을 제거해줄 뿐 아니라 garbage collector가 인스턴스들을 삭제하는 데 소요되는 시간을 줄여준다.

간단히 말해서, 단일의, 그리고 오직 하나의 클래스 인스턴스만 생성되도록 하고자 할 때 Singleton 설계 패턴을 이용하면 된다. 생성자가 연산을 요구하지 않을 경우에는 빈 private 생성자(또는 서브클래스가 필요할 경우에는 보호된 생성자)를 제공한다. 그렇지 않으면 디폴트값으로 시스템이 public 생성자를 제공하게 되는데, 이는 Singleton으로 작업 시 바람직하지 않은 결과라 할 수 있다.

Singleton은 주어진 클래스 로더 내에서만 고유성이 보장된다는 점에 유의할 것. 복수의 서로 다른 엔터프라이즈 컨테이너에 걸쳐 동일한 클래스를 사용할 경우에는 각 컨테이너에 대해 하나의 인스턴스를 얻게 된다.

Singleton 패턴은 종종 Factory 패턴이라 불리는 다른 패턴과 함께 사용되는데, Factory 패턴도 Singleton 패턴과 마찬가지로 생성 패턴의 일종이다. 이 패턴은 특정 객체의 서브클래스, 또는 보다 일반적으로 특정한 인터페이스의 구현이 어떻게 실제로 객체를 생성하는지 기술한다. Factory 패턴의 좋은 보기로 Swing BorderFactory 클래스를 들 수 있다. 이 클래스는 다양한 종류의 Border 객체를 리턴하는 일련의 정적 메소드를 가지는데, 서브클래스의 구현 세부사항을 숨겨서 factory가 인터페이스 구현을 위한 생성자를 직접 호출할 수 있게 해준다. 다음은 BorderFactory의 사용 예제이다.
   Border line = BorderFactory.createLineBorder(Color.RED);
   JLabel label = new JLabel("Red Line");
   label.setBorder(line);
여기서 BorderFactoryLineBorder를 생성한다는 사실이나 그 생성 방법은 숨겨져 있다. 이번 특정 예제에서는 LineBorder 생성자를 직접 호출할 수 있지만 Factory 패턴을 이용하는 대부분의 경우에는 직접 호출이 불가능하다.

Singleton 패턴을 구현하는 클래스는 다른 클래스의 인스턴스를 생성하기 위해 Factory로 사용할 객체를 리턴하는 경우가 흔히 있는데, 이는 PopupFactory 클래스에 의한 Popup 객체 생성 방식에 의해 예증된다.

Singleton factory를 얻으려면 PopupFactorygetSharedInstance() 메소드를 호출한다.
   PopupFactory factory = PopupFactory.getSharedInstance();
그런 다음 factory의 getPopup() 메소드를 호출하여 factory에서 Popup 객체를 생성하고, 상위 컴포넌트, 그 콘텐츠, 포지션을 전달한다.
   Popup popup = factory.getPopup(owner, contents, x, y);
보안 컨텍스트에서 Factory 패턴이 자주 사용되는 것을 볼 수 있을 것이다. 다음 예제에서는 특정 알고리즘에 대한 certificate factory를 획득한 다음 stream certificate를 생성한다.

   FileInputStream fis = new FileInputStream(filename);
   CertificateFactory cf = 
      CertificateFactory.getInstance("X.509");
   Collection c = cf.generateCertificates(fis);
BorderFactory에서 본 것처럼, Factory 패턴이 반드시 Singleton 패턴과 함께 사용되어야 하는 것은 아니지만 실제로는 두 패턴이 함께 사용되는 경우도 종종 볼 수 있다.

But. Singleton 클래스가 단일 클래스 로더를 통해 공유되지 않으면 Singleton이 아님에 주의!!

2007/07/03 18:48 2007/07/03 18:48
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

옵저버 패턴 :: Observer Pattern

Observer 패턴은 자바 프로그램에서 많이 사용되는 설계 패턴이다. 이 패턴은 동작 설계 패턴으로, 클래스가 느슨하게 연결되는 방식과 타 클래스 업데이트 시 하나의(또는 다수의) 클래스가 통지되는 방식을 정의한다. 기본적으로, 이는 특정 장소에서 무슨 일이 발생할 경우, 이를 보고있었거나 관심을 가지고 있던 사람들에게 상황을 통지하는 것을 의미한다.

Observer 패턴을 취급하는 방식에는 두 가지가 있는데, 첫 번째 방식은 java.util package에서 볼 수 있는 ObserverObservable 클래스를 수반하는 것이고, 두 번째 방식은 컴포넌트에 이벤트 리스너를 등록하는 JavaBeans 컴포넌트 모델을 따르는 것이다.

JavaBeans 이벤트 모델 생성에 앞서 ObserverObservable 클래스는 Observable 패턴의 구현을 기술한다. 달리 말해서 이 클래스들은 Java 플랫폼 1.0 버전 때부터 사용되어 왔고, 기술적으로 하자가 없었으며 여전히 라이브러리에 존재하고 있는 것이다. 또한, 이 클래스들은 여전히 Observable 패턴 구현에 사용할 수는 있지만, 두 번째 모델인 JavaBeans 컴포넌트 모델이 일반적으로 사용된다. Observable 패턴 구현을 위해 이 클래스들을 사용하는 데 따른 한 가지 중요한 문제는 Observable 확장이 필요하다는 점인데, 이 경우 자바 플랫폼의 단일 상속 세계에서는 불가능할 수도 있는 클래스 하이어라키 구조를 강요 받게 된다.

이벤트 리스너를 등록하는 JavaBeans 컴포넌트 모델은 일련의 add 및 remove 메소드를 수반하는데, 여기서 리스너 타입은 메소드 이름에 내장되어 있다. 예를 들어, 버튼의 선택을 관찰하기 위해서는 컴포넌트에 ActionListener를 등록한다.
   ActionListener listener = new ActionListener() {
      public void actionPerformed(ActionEvent actionEvent) {
          ...
      }
   }; 
   JButton button = new JButton("Pick Me");
   button.addActionListener(listener);
시스템 정의 클래스를 위한 Observer 패턴은 이것이 전부라고 할 수 있는데, 리스너 인터페이스를 구현하고, 그것을 관찰 Subject에 첨부한 다음 기다린다. Subject는 관찰되는 대상으로, 누가 관찰하고 있는지를 기억하는 일을 책임진다. JavaBeans 컴포넌트 모델의 경우, Observer 객체를 첨부, 분리하기 위한 인터페이스로 add/remove 리스너 네이밍 패턴이 사용된다. Subject의 상태가 변경되면 이를 Observer 객체에 통지한다.

패턴의 주된 목표 중 하나는 Subject와 Observer의 느슨한 연결을 가능케 하는 것이다. JButton이 선택되면, ButtonNotification이라 불리는 가상 서브클래스의 특정 메소드를 호출하는 대신 누구나 구현할 수 있는 인터페이스로 통지가 추상화된다. JButton은 첨부된 Observer(리스너)가 어떤 클래스인지 전혀 개의치 않는데, 실제로 버튼은 구현 클래스가 수정되더라도 오로지 Observer가 리스너를 구현한다는 사실에만 관심을 가진다.

Observer 패턴 사용 시 주의할 필요가 있는 여러 가지 복잡한 문제들이 있다. 첫째는 메모리 누출의 가능성이다. Observer에 대한 레퍼런스는 Subject에 의해 관리되는데, Subject가 레퍼런스를 해제할 때까지는 garbage collector로 Observer를 제거할 수 없다. 이런 가능성에 유의하여 적절한 상황에서 Observer를 제거해야 한다. 아울러 (적어도 이벤트 리스너를 등록할 때는) 일련의 Observer 객체가 unordered collection에서 관리된다는 점에 주목할 것. 먼저 등록된 리스너가 먼저 통지되는지 마지막에 통지되는지를 반드시 알아야 할 필요는 없으나 반드시 객체 A가 먼저 통지되고 이어서 객체 B가 통지되는 cascading 방식의 통지가 필요한 경우에는 중간 객체를 도입하여 순서가 지켜지도록 해야한다. 단지 Observer를 특정 순서로 등록한다고 해서 반드시 그 순서에 따라 통지가 이루어지는 것은 아니다.

Observer 패턴을 모델링하는 자바 플랫폼의 또 다른 영역으로는, guaranteed delivery, non-local distribution, persistence 등의 이점을 갖춘 JMS(Java Message Service)를 들 수 있다. JMS publish-subscribe 메시징 모델은 무한한 수의 가입자가 관심 있는 주제를 청취할 수 있게 해주는데, publish된 주제에 대한 메시지가 생성되면 모든 가입자들에게 내용이 통지된다.

그 밖에도 자바 플랫폼에는 Observer 패턴을 모델링하는 여러 다른 분야가 있으며, 이 패턴은 자바 플랫폼 전반에 걸쳐 자주 사용된다.
2007/07/03 18:46 2007/07/03 18:46
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

생성패턴(creational pattern) :: 디자인 패턴

Abstract Factory



Abstract Factory 패턴의 구조는 위 그림과 같다. AbstractFactory라는 추상 클래스가 있고, 그 추상 클래스는 필요한 객체들을 생성하는 인터페이스를 가지고 있다. 실제로 객체를 생성하는 역할을 맞는 클래스(ConcreteFactory)들은 AbstractFactory 추상클래스를 상속하고 객체 생성 인터페이스를 구현한다. AbstractFactory 추상 클래스를 상속하는 ConcreteFactory를 여러 종류 만들 수도 있는데 각 클래스가 하나의 객체 Family를 이루게 된다. Client는 ConcreteFactory가 생성하는 실제 객체들(Product..)들의 부모인 AbstractProduct에 대해서만 알고 있어도 된다.
Abstract Factory 패턴은 ConcreteFactory만 교체하면 전체 Product들이 바뀌는 효과를 낼 수 있다. 흠..내 생각에 이런 것이 필요한 대표적인 경우로는 인터페이스의 스킨기능을 들 수 있을 것 같다. 책에도 이 패턴이 대표적으로 사용되는 경우가 인터페이스의 구성요소를 통째로 갈아끼우는 식의 구현이 필요할 때라고 적혀 있다.

Builder


Builder 패턴의 구조는 위 그림과 같다. Director가 Builder에게 어떤 객체의 생성을 요청하면 Builder가 척척 만들어서 Director에게 제공한다. 객체 생성을 전담하는 클래스가 따로 있다는 점에서 Abstract Factory패턴과 비슷하긴 한데, 약간 다른 점은 주로 Builder패턴은 복잡한 객체를 순서대로(step by step)만드는 반면 Abstract Factory 패턴은 주로 한 종류로 구분할 수 있는(Family) 객체들을 만드는 것에 중점을 두고 있다.

Factory Method


Factory Method패턴은 가장 간단한 생성 패턴이라고 한다. 별거 없이 객체를 직접 new로 생성하지 않고 FactoryMethod를 통해서 생성하는 방법이다. 흠..나름대로 Creator를 여러가지로 상속해서 확장을 꾀할 수 있다.

Prototype



가장 이해하기 힘들었던 패턴이다. 아직도 언제 어떻게 사용해야 할지 잘 모르겠다. C++관점으로 설명하자면. Client는 Prototype 추상 클래스의 포인터를 가지고 있다. Client가 생성될 때 적당한 ConcretePrototype(Prototype추상 클래스를 상속한 구체 클래스)를 생성하여 Client가 가지고 있는 Prototype포인터에 대입해서 유지 한다. Client가 객체를 생성하고 싶을 때 Prototype포인터에 Clone함수를 호출해서 생성한다.
Prototype 패턴의 핵심은 바로 Clone인터페이스 이다!

Singleton
Singleton패턴은 전체 프로세스 상에서 객체가 유일하게 생성되는 클래스를 정의하는 패턴이다. 이 이야기는 More Effective C++에 이미 나왔던 이야기인데, 클래스의 생성자를 public으로 하지 않으면 직접 클래스의 객체를 생성할 수 없게 된다는 점을 이용하면 된다.
클래스의 생성자를 protected나 private으로 하고, 클래스의 객체를 생성하는 인터페이스를 따로 만든다.
간단한 소스로 이해 해보자.

  1. class Singleton {
  2.   public:static void Singleton* Instance();
  3.   protected:static Singleton();
  4.   private:static Singleton* _instance;
  5. };
  6.  
  7. Singleton* Singleton::_instance = 0;
  8.  
  9. Singleton* Singleton::Instance(){
  10.   if(_instance == 0){
  11.     _instance = new Singleton;
  12.   }
  13.   return _instance;
  14. }



2007/06/22 14:44 2007/06/22 14:44
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

디자인 패턴 for 자바 :: Design Pattern for JAVA

2005년도 한창 패턴에 관심을 갖던 시기에 구한 도표인데.. 출처는 기억이 나질 않는군요..

디자인패턴 Design Pattern

2007/06/21 17:50 2007/06/21 17:50
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

구조패턴(structual pattern) :: 디자인 패턴

구조 패턴이라고 해석할 수 있을까나? structural pattern들은 객체들을 잘 구슬려서 어떤 구조를 만들어 내는 패턴들이다. 분류가 왜 이렇게 된 건지 잘 이해가 되진 않는다. 여하튼 패턴들을 살펴보자.

Adapter

Adapter패턴은 인터페이스가 서로 맞지 않는 두 클래스 사이에서 인터페이스를 맞춰주는 역할을 한다. Adaptee라는 클래스가 이미 존재한다고 하자.(어디 존재하는지는 별로 중요하지 않고..라이브러리 안쪽에 있을수도.. 소스코드로 있을수도..) Target에서 뭔가 작업을 하려고 하는데 그 작업이 이미 Adaptee에 구현된 작업과 매우 유사하다. 그런데 Target과 Adaptee의 인터페이스 구조가 달라서 어떻게 하기가 좀 곤란하다. 그럴 때 Adapter패턴을 사용한다. Adapter는 Target을 public상속(interface 상속)하고, Adaptee는 private상속을 해서(implementation만 상속한다는 뜻) Adapter에서는 Target의 인터페이스를 Adaptee의 구현을 이용해 구현하면 된다.(위쪽 그림 – Class Adapter)
private상속을 이용하지 않고 Adapter가 Adaptee를 멤버로 가지고 직접 Adaptee객체를 이용해 Adaptee의 구현을 활용할 수도 있따.(아래 그림 – Object Adapter)

실제 예를 들어 설명하면, Shape라는 추상 클래스가 있다. 어떤 모양을 나타내는 것일 테다. 이놈을 상속해서 LineShape도 만들 수 있고, CircleShape도 만들 수 있을 거다. TextShape도.. 그런데 TextShape를 만들려고 하다 보니 이미 TextView라는 이름으로 구현하려고 했던 대부분의 기능이 구현되어 있는 클래스가 있다고 해보자. TextShape를 TextView의 구현을 이용해서 만들고 싶다. 이럴 때 Adapter패턴을 적용하면 딱 이다. TextShape를 Shape를 public상속, TextView를 private상속하게 하거나, TextShape가 TextView의 객체를 가지고 구현을 이용하게 하거나 하면 될 것이다.


Bridge

이 패턴을 클래스의 추상부분과 구현을 분리 시켜서 뭔가를 얻어 보려는 패턴이다. 이게 여러모로 쉽게 확장을 할 수 있게 해준다. 역시 예를 들어 알아보자. 책에 나와 있는 Window시스템을 보자.
그냥 생각해서 Window를 나타내는 추상 클래스가 있고, 이놈을 상속해서 XWindow시스템, PMWindow시스템 이렇게 늘려간다고 해보자. 이제 아이콘을 나타내기 위해 IconWindow라는 놈을 만들려고 하면, XWindow용으로 XIconWindow도 만들어야 하고, PMWindow용으로 PMIconWindow도 만들어야 한다. 계속 추가 시켜나가야 할 양이 많아진다. 즉 확장이 쉽지 않다.
이런 놈을 Bridge패턴을 적용해서 이렇게 만들면 어떨까? Window라는 추상 클래스를 만든다. 그리고 WindowImp라는 구현을 담당하는 추상 클래스를 만든다. Window를 상속하여 IconWindow, TransientWindow등을 만든다. 이때 이 클래스들의 인터페이스는 WindowImp를 상속한 클래스들의 구현을 이용해서 구현한다. WindowImp를 상속하여 XWindowImp, PMWindowImp를 만들 수 있을 거고, Window를 상속하는 놈들은 이렇게 구현된 것들을 이용해서 만드는 것이다. 흠.. 이때 XWindowImp와 PMWindowImp는 Window를 상속하는 클래스들에서 필요할 만한 기본적인 구현들을 포함하고 있어야 한다.


Composite

Composite패턴은 쉽게 말해 묶음을 지을 수 있게 하고, 묶음을 낱개하고 똑같이 취급할 수 있게 하는 패턴이다.
흠..위 그림을 보면 Component 추상 클래스가 있다. 이것을 상속해서 Leaf클래스를 만들 수도 있고, Composite클래스를 만들 수도 있다. Composite클래스는 Component들을 Child로 포함할 수 있다. Composite도 Compnent니까 Composite가 Composite를 recursive하게 포함할 수 있다는 소리다. 이런 패턴을 주변에서 많이 볼 수 있다. 흠..컴퓨터 시스템만 해도 그렇다. 몇 개의 부품을 모으면 하나의 모듈이 되고 그 모듈이 또 전체 컴퓨터 시스템에 참가 하고.. 어쩌고 저쩌고.. 궁시렁 궁시렁..


Decorator

Decorator는 이름에 걸맞게 장식을 하는 패턴이다.
후훗. 그러니까.. Decorator는 Component를 상속하고 Component하나를 자기 안에 가지고 있는다. 그리고 Operation을 할 때 그 가지고 있던 Component의 Operation을 수행한다. 이때, Decorator는 그 Operation외에 어떤 작업(AddedBehavior)를 추가적으로 수행한다. 기본 작업(Component의 Operation)에 어떤 작업(AddedBehavior)를 추가 해서 장식을 하는 것이다. 실례를 들어 보자.
어떤 인터페이스 시스템에 VisualComponent라는 추상클래스가 있다. 그 추상 클래스를 상속하여 여러 인터페이스 요소들을 만드는데 TextView라는 것이 있다고 하자. 이 TextView를 포함한 VisualComponent들에 ScrollBar나 Border를 추가하고 싶다고 할 때, Decorator패턴을 사용할 수 있다.

위 그림을 보라!


Facade

Facade패턴은 조금 단순하다. 아래 그림을 보라.

이렇게 subsystem들을 외부에 공개하는 객체를 만드는 패턴을 Facade패턴이라고 한다.


Flyweight

이 패턴은 아주 자주 사용되는 객체들을 공유해서 과도한 메모리 사용량을 줄일 수 있는 패턴이다.(과도하다기 보다는 거의 구현 불가능한 정도의 메모리 사용량을 필요로 하는 경우라고 할 수도 있겠다.) 대표적인 예로, 문서 편집기를 만들 때, 각 글자 객체들을 관리하는 예가 책에 제시되어 있다. 아래 다이어그램을 보자.

GlyphFactory는 _character에 Character클래스의 객체들을 쭉 가지고 있는다. Character의 종류라고 해봤자 얼마 안될 것이기 때문에 쭉 가지고 있으면서 공유해서 사용하면 된다. 위의 경우 글자의 폰트등은 GlyphContext에서 관리해서 꾸며준다. 흠..자세히 이해하긴 힘들어서 더 이상 설명은 곤란..ㅠ.ㅠ

Proxy

Proxy패턴은 어떤 객체를 대신하는 Proxy객체를 만드는 패턴. 네트워크 저편에 있는 어떤 객체를 대신하는 remote proxy, 객체가 너무 커서 꼭 필요할 때만 생성해서 사용하게 큰 객체를 대신하는 virtual proxy, 원래 객체를 숨겨서 권한에 따라 접근 성을 다르게 주게 할 수 있는 protection proxy, 스마트 포인터등의 smart reference등으로 사용할 수 있는 패턴이다.
2007/06/21 17:44 2007/06/21 17:44
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

디자인 패턴 ( Design Pattern )의 구분

객체지향 방법론의 가장 큰 장점인 재사용성과 모듈성을 극대화시켜 실제 구현 과정에서의 해결 방안으로 제시 가능한 것으로 이를 적용하면 시스템 개발은 물론 유지 보수에서도 큰 효과가 있다.     

  • 상위 단계에서 적용될 수 있는 개념          
  • 디자인뿐만 아니라 시스템 구조를 재사용 하기 쉽게 만들 수 있다.          
  • 개발에 따른 산출 문서를 보다 향상시킬 수 있다.          
  • 불명확한 클래스의 기능, 객체간의 부적절한 연관 관계 등을 제거해 현존하는 시스템에 대한 유지 보수도 용이하다.          
  • 제대로 만들어진 디자인을 보다 빠르게 얻어낼 수 있는 이점이 있다.          
  • 일반적인 설계 문제에 대한 솔루션을 제공하는 객체와 클래스와의 연관 관계를 묘사한 것이다.

[패턴의 분류와 종류]


기본 패턴(Fundamental Design Patterns)

  • 디자인 패턴 중에서도 가장 기본인 동시에 가장 중요한 패턴                 
  • 종류 : 델리게이션(Delegation) 패턴, 인터페이스 패턴, 이뮤터블(Immutable)패턴, 마커 인터페이스(Marker Interface) 패턴, 프록시(Proxy) 패턴 등

    생성 패턴(Creational Patterns)

  • 객체의 생성 방식을 결정하는데 포괄적인 솔루션을 제공하는 패턴                  
  • 클래스 정의와 객체 생성 방식을 구조화, 캡슐화하는 방법을 제시한다.                                  
  • 객체 생성 과정을 추상화시킨다는 특성을 갖고 있으며 클래스의 재사용을 위해 상속보다는 컴포지션 기법을 보다 많이 사용한다.                                  
  • 기본원리
                                    ① 시스템에서 사용하는 클래스 정보를 캡슐화
                                    ② 클래스에 의해 객체가 생성되는 방식                                  
  • 이점 : 전체적인 시스템 구성의 유동성이 향상되어 객체 행성 방식이 다양한 구조로 진행될 수 있다. 예를 들어, 객체의 구성을 컴파일 타임에 정적으로 정의할 수 있으며 필요에 따라 런타임에 동적으로 구성할 수 있다.                                  
  • 종류 : 팩토리 메쏘드(Factory Method) 패턴, 추상화 팩토리(Abstract Factory) 패턴, 프로토타입(Protytype) 패턴, 싱글턴(Singleton) 패턴, 오브젝트 풀(Object Pool) 패턴 등    

    분류 패턴(Partitioning Patterns)

  • 분석 단계에서 일반적으로 생기는 문제를 해결하는데 적합하다.                                  
  • 복잡한 행위자(Actors)를 분류하거나 비교적 큰 기능을 분류해 여러 클래스로 정의하는 방식을 제시한다.                                  
  • 종류 : 계층적 초기화(Layered Initialization) 패턴, 필터(Filter) 패턴, 컴포지트(Composite) 패턴 등

    구조화 패턴(Structural Patterns)

  • 다른 기능을 가진 객체가 협력을 통해 어떤 역할을 수행할 때, 객체를 조직화시키는 일반적인 방식을 제시한다.                                  
  • 클래스와 객체가 보다 대규모 구조로 구성되는 방법에 대한 해결안을 제시한다.                                 
  • 별도로 구성된 클래스 라이브러리를 통합하는데 유용하다.                                  
  • 생성 패턴과 달리 새로운 기능을 구현하기 위해 객체를 구성하는 방식 자체에 초점이 맞춰져 있다.                                
  • 런타임에 객체 컴포지션 구조를 변경할 수 있으며, 이를 통해 객체 구성에 유동성과 확작성을 추가할 수 있다.                                  
  • 종류 : 어댑터(Adapter) 패턴, 이터레이터(Iterator) 패턴, 브리지(Bridge) 패턴, 퍼케이드(Facade) 패턴, 플라이웨이트(Flyweight) 패턴, 디이나믹 링키지(Dynamic Linkage) 패턴, 가상 프록시(Virtual Proxy) 패턴 등  

    행위 패턴(Behavioral Patterns)

  • 객체의 행위를 조직화(organize), 관리(manage), 연합(combine)하는데 사용되는 패턴                                  
  • 객체간의 기능을 배분하는 일과 같은 알고리즘 수행에 주로 이용된다.                                  
  • 단지 객체나 클래스에 대한 유형을 정의하는 것이 아니라 그들 간의 연동에 대한 유형을 제시한다.                                 
  • 런타임에 따르기 어려운 복잡한 제어 흐름을 결정짓는데 사용할 수 있다.                                  
  • 객체의 인터커넥트(intercnnnect)에 초점을 맞춘 패턴        

  • 2007/06/19 19:18 2007/06/19 19:18
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다