2015년 10월 16일 금요일

클래스 디자인 패턴 13. Prototype pattern

1. 개념
  1) 의미
     new 연산자를 사용하면서 클래스를 지정하지 않고 인스턴스를
       생성하려는 경우 클래스가 아닌 기존의 인스턴스를
       복사해야 하는 경우가 있습니다.
     목적 인스턴스가 취급하는 객체가 여러개인 경우, 복잡한
       과정을 통해서 인스턴스가 생성되거나 사용자 작업으로
       인스턴스가 생성되어 이를 클래스에서 재생성이 불가한
       경우 사용하고 있는 클래스와 별도로 관리하고자 하는 경우
       가 있습니다.
     인스턴스로 새로운 인스턴스를 생성하는걸 Prototype Pattern
       이라고 합니다.
   
  2) 참고자료
     Prototype pattern 위키백과    https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85_%ED%8C%A8%ED%84%B4


2. 소스
 
  1) 인스턴스를 사용할 수 있게 할 Product 클래스 작성
       여기서 어떤 메서드가 인스턴스를 복사할지 강제합니다.

public interface Product extends Cloneable{
public abstract void use(String s);
public abstract Product createClone();
}


  2) Product 를 이용해서 인스턴스를 실제로 복제하는 기능을
      담당하는 Manager 클래스 작성

import java.util.Hashtable;

public class Manager {
private Hashtable showcase = new Hashtable();

public void register(String name, Product proto){
showcase.put(name,  proto);
}

public Product create(String protoname){
Product p = (Product) showcase.get(protoname);
return p.createClone();
}
}


  3) 인스턴스 복제 목적 클래스인 MessageBox 클래스 작성
       여기서 CreateClone에서 사용한 clone 메서드는
       자바에서 제공하는 자신의 인스턴스 복제 메서드 입니다.
       clone 사용시 Cloneable을 상속해야 합니다. (여기서는
      Product가 해당 업무를 대신함)
       그리고 clone는 해당 인스턴스 만을 복사하기 때문에
       추가적인 정보까지 같이 복사해야 하는 경우엔 해당
       clone 메서드를 오버라이드 해야합니다.

public class MessageBox implements Product {
private char decochar;
public MessageBox(char decochar){
this.decochar=decochar;
}

@Override
public void use(String s) {
int length = s.getBytes().length;
for(int i=0; i<length; i++){
System.out.print(decochar);
}
System.out.println(" ");
System.out.println(decochar+" "+s+" "+decochar);
for (int i=0; i<length+4;i++){
System.out.print(decochar);
}
System.out.println("");
}

@Override
public Product createClone() {
Product p =null;
try{
p = (Product)clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return p;
}
}


  4) 이를 테스트 하기 위한 코드
       여기서 객체 셋팅 부분은 이전에 진행된 부분이고
       주목할 점은 Product 만 가지고 클래스 상관없이
       인스턴스를 복사해서(register), 쓸수(use) 있습니다
       

public class MainTest {
public static void main(String[] args) {

//객체 셋팅
Manager manager = new Manager();
MessageBox mbox = new MessageBox('*');
MessageBox sbox = new MessageBox('/');
manager.register("warning box", mbox);
manager.register("team is good", sbox);
//기존에 만들어진 객체를 사용하는 부분
Product p2 = manager.create("warning box");
p2.use("team is good");
Product p3 = manager.create("team is good");
p3.use("hello, southAfrica");
}
}


결과 : 
************
* team is good *
****************
//////////////////
/ hello, southAfrica /
//////////////////////



3. 다이어그램

https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85_%ED%8C%A8%ED%84%B4


4. 관련패턴
  1)Flyweight 패턴
      Prototype은 현재 인스턴스와 같은 다른 인스턴스를 생성해서
       복사한 인스턴스를 사용하는데
     Flyweight 의 경우엔 한 인스턴스를 등록 후 이걸 여러
       장소에서 공유해서 사용합니다.

  2) Memento 패턴
    이 패턴은 undo, 스냅샷 같은 이전으로 돌아가는 명령을
       실행하도록 현재 인스턴스 상태를 보존합니다.

  3) Composite 및 Decorator
    위 패턴 사용시에 Prototype 패턴을 이용해서 구현시
      반복작업을 감소시킵니다.

  4) Command 패턴
   명령 복제시 Prototype패턴이 사용되는 경우가 이습니다.

댓글 없음:

댓글 쓰기