Prototype패턴

인스턴스를 만들때 new연산자를 쓰는게 아니라 어떤 인스턴스로부터 인스턴스를 만드는 패턴입니다.

 

 

 

 

 

 

framework패키지의 Product 클래스

 

package framework;

 

public interface Product extends Cloneable{//Cloneable인터페이스를 상속받아야 clone메소드 사용 가능

       public abstract void use(String s);

       public abstract Product createClone();//복사본을 만드는 메소드

 

}

 

 

framework패키지의 Manage클래스

 

package framework;

 

import java.util.HashMap;

 

public class Manager {

       /**

        * @uml.property name="showcase"

        * @uml.associationEnd qualifier="protoname:java.lang.String framework.Product"

        */

       private HashMap showcase = new HashMap();//해쉬테이블을 만들고

      

       public void register(String name, Product proto){

             showcase.put(name, proto);//name index 두고 내용물은 proto 둔다

       }

       public Product create(String protoname){//index 주면 내용물을 불러올수 있게함

             Product p = (Product)showcase.get(protoname);

             return p.createClone();//내용물은 복사본으로 결국 여기서 new 해서 인스턴스를 만드는 효과가 일어난다

       }

}

 

 

익명패키지의 MessageBox클래스

 

import framework.Product;

 

//*******

//*hello*

//*******

// 모양 꾸미는 클래스

 

 

public class MessageBox implements Product{

 

       /**

        * @uml.property name="decochar"

        */

       private char decochar;

      

       public MessageBox(char decochar){

             this.decochar = decochar;

       }

      

       @Override//자기자신을 복제하는 메소드

       public Product createClone() {

             // TODO Auto-generated method stub

             Product p = null;

             try{//예외가 발생할 수도 있어서

                    p = (Product)clone();//clone메소드로 복사가능한것은 Cloneable 인터페이스를 구현하고 있는 클래스뿐

                    // Product클래스만 복사가능 shallow copy

 

             }catch(CloneNotSupportedException e){

                    e.printStackTrace();

             }

            

             return p;

       }

 

       @Override

       public void use(String s) {

             // TODO Auto-generated method stub

             int length = s.getBytes().length;//스트링의 길이를 바이트 단위로 읽음

             for(int i = 0; i < length + 4; i++){//************부분

                    System.out.print(decochar);

             }

            

             System.out.println("");

             System.out.println(decochar + "" + s + "" + decochar);//*hello*부분

            

             //***********부분

             for(int i = 0; i < length + 4; i++){

                    System.out.print(decochar);

             }

             System.out.println("");

       }

      

      

}

 

 

익명패키지의 UnderlinePen클래스

 

 

 

import framework.Product;

 

//"hello"

//~~~~~~~

// 꾸미는 클래스

public class UnderlinePen implements Product{

       /**

        * @uml.property name="ulchar"

        */

       private char ulchar;

       public UnderlinePen(char ulchar){

              this.ulchar = ulchar;

       }

       @Override

       public Product createClone() {

             // TODO Auto-generated method stub

             Product p = null;

             try{//예외가 발생할 수도있어서 써줌

                    p = (Product)clone();//마찬가지로 자기자신의 복제를 생성하는 메소드 shallow copy

             }catch(CloneNotSupportedException e){

                    e.printStackTrace();

             }

            

             return p;

       }

       @Override

       public void use(String s) {

             // TODO Auto-generated method stub

      

             int length = s.getBytes().length;//바이트 단위로 읽어옴

             System.out.println("\"" + s + "\"");//"hello"부분

             System.out.print("");

            

             //~~~~~~~부분

             for(int i = 0; i < length; i++){

                    System.out.print(ulchar);

             }

             System.out.println("");

       }

      

      

}

 

 

익명패키지의 Main클래스

 

import framework.Manager;

import framework.Product;

 

 

public class Main {

 

       /**

        * @param args

        */

       public static void main(String[] args) {

             // TODO Auto-generated method stub

             //준비

             Manager manager = new Manager();

             UnderlinePen upen = new UnderlinePen('~');

             MessageBox mbox = new MessageBox('*');

             MessageBox sbox = new MessageBox('/');

             manager.register("strong message", upen);

             manager.register("warning box", mbox);

             manager.register("slash box", sbox);

            

             //생성

             Product p1 = manager.create("strong message");//결국 new 같은 효과가 일어나게됨

             p1.use("Hello, world.");

             Product p2 = manager.create("warning box");

             p2.use("Hello, world.");

             Product p3 = manager.create("slash box");

             p3.use("Hello, world.");

       }

 

}

 

 

 

new로 안하고 이렇게 할까?

1. 종류가 너무 많아서 클래스로 정리할 수 없는 경우

예제에서는 ~을 사용 *을 사용 /을 사용 3개지만 많아지면 여러개의 클래스를 만들어야합니다. 그 불편함을 줄이기 위해서 이 패턴을 씁니다.

2. 클래스로부터 인스턴스 생성이 어려운 경우

이 예제에서는 실감이 안나지만 사용자가 포토샵으로 어떤 도형을 복사하고싶다면 처음부터 생성해서 똑같이 그리는 것보다 그냥 단순히 그 도형을 복사하는 것이 빠를 것입니다.

3. framework와 생성하는 인스턴스를 분리하고 싶은 경우

일종의 new Something이라는 인스턴스 생성방법에서 클래스를 써야한다는 점을 벗어나기 위해서 입니다. 즉 예제를 보면 strong message같은 것으로 인스턴스를 생성한 점입니다.

마지막 3번의 경우 객체지향프로그래밍에 해당하는 것입니다. 항상 클래스 이름을 써야된다는 점에 구속된다면 재사용면에서 보면 안좋을 수 밖에 없습니다. 그래서 이런식으로 클래스명에 구애받지 않게 인스턴스를 생성하는 것이 좋습니다.

블로그 이미지

가카리

프로그래밍, 취업 및 직장생활, 주식 부동산 재테크 전문 블로그

댓글을 달아 주세요