Design Pattern | Prototype Pattern (프로토타입 패턴)


Prototype 패턴이란?

  • Prototype이라는 영엉 단어는 원형이나 모범 이라는 의미가 된다.
  • Prototype 패턴은 new Xxx()으로 클래스로부터 인스턴스를 생성하는 것이 아니라, 인스턴스로부터 다른 인스턴스를 생성하는 방식이다. 즉, 복사하여 인스턴스 만드는 것이다.
  • 복제를 만드는 작업을 clone 이라고 한다.
  • GoF 디자인 패턴에서는 생성과 관련된 디자인 패턴으로 분류된다.

Prototype 패턴 예제 프로그램

입력한 문자열에 밑줄을 그거나 둘러싸는 예제 프로그램이다.

Class Diagram
Prototype Pattern Class Diagram

1. Product 인터페이스

복제 메소드를 정의하는 인터페이스이다. java의 Cloneable 인터페이스를 상속한다.

Product.java

package com.devkuma.designpattern.creational.prototype.framework;

import java.lang.Cloneable;

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

    Product createClone();
}

2. Manager 클래스

Product의 생성 지시나 관리를 실시하는 클래스이다.

Manager.java

package com.devkuma.designpattern.creational.prototype.framework;

import java.util.HashMap;

public class Manager {

    private HashMap showcase = new HashMap();

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

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

3. UnderlinePen 클래스

Product 인터페이스를 구현하는 클래스입니다. 당 클래스는 「문자에 밑줄을 긋는」클래스가 됩니다.

UnderlinePen.java

package com.devkuma.designpattern.creational.prototype.product;

import com.devkuma.designpattern.creational.prototype.framework.Product;

public class UnderlinePen implements Product {

    private char underlineChar;

    public UnderlinePen(char underlineChar) {
        this.underlineChar = underlineChar;
    }

    public void use(String s) {

        int length = s.getBytes().length;

        System.out.println(s);

        for (int i = 0; i < length; i++) {
            System.out.print(underlineChar);
        }

        System.out.println();
    }

    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            // 객체의 클래스가 Cloneable 인터페이스를 구현하고 있지 않은 경우에 Throw되는 예외
            e.printStackTrace();
        }
        return p;
    }
}

4. MessageBox 클래스

Product 인터페이스를 구현하는 클래스입니다. 당 클래스는 「문자를 둘러싼」클래스가 됩니다.

MessageBox.java

package com.devkuma.designpattern.creational.prototype.product;

import com.devkuma.designpattern.creational.prototype.framework.Product;

public class MessageBox implements Product {

    private char decoChar;

    public MessageBox(char decoChar) {
        this.decoChar = decoChar;
    }

    public void use(String s) {

        int length = s.getBytes().length;

        for (int i = 0; i < length + 2; i++) {
            System.out.print(decoChar);
        }

        System.out.println();
        System.out.println(decoChar + s + decoChar);

        for (int i = 0; i < length + 2; i++) {
            System.out.print(decoChar);
        }

        System.out.println();
    }

    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            // 객체의 클래스가 Cloneable 인터페이스를 구현하고 있지 않은 경우에 Throw되는 예외
            e.printStackTrace();
        }
        return p;
    }
}

5. Main 클래스

메인 처리를 실행하는 클래스이다.

Main.java

package com.devkuma.designpattern.creational.prototype;

import com.devkuma.designpattern.creational.prototype.framework.Manager;
import com.devkuma.designpattern.creational.prototype.framework.Product;
import com.devkuma.designpattern.creational.prototype.product.MessageBox;
import com.devkuma.designpattern.creational.prototype.product.UnderlinePen;

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

        Manager manager = new Manager();
        UnderlinePen upen = new UnderlinePen('~');
        MessageBox mbox = new MessageBox('*');
        MessageBox pbox = new MessageBox('+');
        manager.register("strong message", upen);
        manager.register("warning box", mbox);
        manager.register("slash box", pbox);

        Product p1 = manager.create("strong message");
        p1.use("Hello world");
        System.out.println();
        Product p2 = manager.create("warning box");
        p2.use("Hello world");
        System.out.println();
        Product p3 = manager.create("slash box");
        p3.use("Hello world");
    }
}

6. 실행 결과

Hello world
~~~~~~~~~~~

*************
*Hello world*
*************

+++++++++++++
+Hello world+
+++++++++++++

Prototype 패턴의 장점

예제 프로그램에서는 비교적 단순한 경우였지만, 인스턴스를 생성하는데 있어서 복잡한 처리가 필요하거나 시간이 걸리는 처리가 필요할 수도 있다. 인스턴스를 생성할 때마다 new Xxx()로서는, 매우 비효율적이다.
Prototype을 만들고 복사하면 쉽게 인스턴스를 생성할 수 있다.