본문 바로가기

Design Patterns/영문 위키(Wikipedia)

Prototype pattern (프로토타입 패턴)

먼저 이 글은 영문 위키의 글을 번역한 글임을 알려드립니다.

영어 실력이 부족하여 오역이 있을 수도 있습니다.

원문 주소 : http://en.wikipedia.org/wiki/Prototype_pattern



생성 패턴 - 프로토타입



The prototype pattern(이하 프로토타입 패턴)은 프로토타입(원형, 기본틀 등으로 해석할 수 있겠네요.) 객체에 의해 생성될 객체의 타입이 결정되는 생성 디자인 패턴이다. 이 패턴은 새로운 객체를 생성하기 위해 clone(복제)을 이용한다. 

이 패턴은 

  • 클라이언트 어플리케이션에서 객체 생성자의 서브 클래싱을 피한다.(반대로 추상 팩토리 패턴에서는 객체 생성자를 서브 클래싱해야만 한다.)
  • 주어진 애플리케이션에서 일반적인 방법(new 키워드를 이용한 방법)으로 객체를 생성할 때에 필요한 비용이 엄청난 경우에 이 비용을 없앨 수 있다.


이 패턴을 구현하기 위해, pure virtual(순수 추상 메서드라고 하면 되나요?... 전 원래 그냥 퓨어 버츄얼이라고 읽어서..) clone()메서드를 가지는 추상 클래스를 선언한다. polymorphic constructor(다형적인 생성자)가 필용한 어떤 클래스든지 추상 클래스를 상속받아서 clone()메서드를 구현해야 한다.

클라이언트는 new 연산자와 클래스 이름을 같이 쓰기보다는 프로토타입 객체의 clone()메서드를 호출하거나, 팩토리에 원하는 클래스에 해당하는 인자를 넣어서 호출하거나, 다른 디자인 패턴에 의해 제공되는 어떤 메커니즘을 통해 clone()메서드를 호출할 수도 있다.


구조 Structure



예 Example

프로토타입 패턴은 프로토타입 객체를 이용해서 어떤 종류의 객체를 생성할 지 정할 수 있다. 새로운 객체의 프로토타입은 종종 완전히 만들어지기 전에 생성이된다. 하지만 이 예에서는 프로토타입이 수동적이고(passive) 스스로는 복제하지는 않는다. 세포의 유사분열(두개의 독립적인 세포가 만들어진다.)은 프로토타입의 한 예이다. 유사분열은 스스로는 복제하는 일을 하기 때문에 프로토타입 패턴의 실례라 할 수 있다. 세포가 분열될 때, 두개의 독립적인 유전자 형이 결과물로 나온다. 다른 말로 세포가 스스로를 복제한다는 말이다. 


Java



/**
 * Prototype class
 */
abstract class Prototype implements Cloneable {
        @Override
        public Prototype clone() throws CloneNotSupportedException {
                return (Prototype)super.clone();
        }
 
        public abstract void setX(int x);
 
        public abstract void printX();
 
        public abstract int getX();
}
 
/**
 * Implementation of prototype class
 */
class PrototypeImpl extends Prototype {
        int x;
 
        public PrototypeImpl(int x) {
                this.x = x;
        }
 
        public void setX(int x) {
                this.x = x;
        }
 
        public void printX() {
                System.out.println("Value :" + x);
        }
 
        public int getX() {
                return x;
        }
}
 
/**
 * Client code
 */
public class PrototypeTest {
        public static void main(String args[]) throws CloneNotSupportedException {
                Prototype prototype = new PrototypeImpl(1000);
 
                for (int i = 1; i < 10; i++) {
                        Prototype tempotype =  prototype.clone();
 
                        // Usage of values in prototype to derive a new value.
                        tempotype.setX( tempotype.getX() * i);
                        tempotype.printX();
                }
        }
}
 
/*
**Code output**
 
Value :1000
Value :2000
Value :3000
Value :4000
Value :5000
Value :6000
Value :7000
Value :8000
Value :9000
*/


경험에 의한 규칙 Rules of Thumb

때때로 생성 패턴은 겹친다. - 프로토타입이나 추상팩토리 둘 중 하나가 적절한 경우가 있다. 

또 다른 경우에 생성 패턴들은 상호 보완적이기도 하다. : 추상 팩토리는 제품 객체를 복제해서 리턴해주기 위해 프로토타입의 집합을 저장하고 있을 수 있다. 추상 팩토리, 빌더, 프로토타입은 각자의 구현에 싱글톤을 사용할 수도 있다. 

추상 팩토리는 종종 팩토리 메서드로 구현되기도하지만(상속 inheritance을 통해 제품 객체를 생성하는 경우), 프로토타입을 이용해서 구현할 수도 있다.(위임 delegate를 이용해 생성하는 경우)


종종 설계자가 어디에서 더 유연한 설계가 필요한지를 발견하기 때문에,  설계는 팩토리 메서드를 사용해서 시작하고 추상 팩토리, 프로토타입, 똔느 빌더 등으로 발전할 수 있다.


프로토타입은 서브클래싱이 필요없지만, 초기화"initialize" 메서드를 필요로한다. 팩토리 메서드는 서브클래싱이 필요하지만, 초기화는 불필요하다.


콤포짓(Composite)과 데코레이터(Decorator)패턴을 많이 사용하는 설계에서는 종종 프로토타입을 사용하는 것이 좋을 수 있다. 


경험에 의하면 런타임시에 당신이 복제하기 위하는 객체를 트루 카피(true copy)해서 생성하고 싶을 때 clone()메서드가 필요할 수 있다. True copy라하면 새로 생성되는 객체의 모든 속성(attributes)이 그를 복제해내는 객체와 같아야 한다는 것이다. 만약 당신이 new를 사용해서 그 클래스를 초기화할 수 있었다면, 초기값들을 속성으로 가진 객체를 얻어냈을 것이다. 예를 들어, 당신이 은행 거래를 수행하는 시스템을 설계했다고 하면, 당신은 자신의 계좌 정보를 가지고 있는 객체를 복사하고, 복제된 객체를 이용해 거래를 하고나서 수정된 객체로 기존 객체를 덮고 싶을 것이다. 이러한 경우에 당신은 new 대신 clone()을 사용하고 싶을 것이다.