Help us understand the problem. What is going on with this article?

デザインパターン入門 Prototype

More than 1 year has passed since last update.

デザインパターン入門 Prototype

概要

Prototypeパターンとは

  • Prototype:"試作品"からインスタンスを生成する。クラスからではない。
  • Cloneableインターフェースを実装し、自身からクローンを作成できる実体クラスがある。

ミソ

四角形を描くと言ったようなアクションが共通しているが、そのとき

  • "/"で囲む四角形
  • "*"で囲む四角形
  • "x"で囲む四角形

と言ったような分かれ方をした3つの雛形があるとき、それぞれを別クラスで作っていてはキリが無い。

描く図形の形だけクラス分けをして、線の種類はClientにそれぞれ同一クラスとしてマッピングしておく。

そして同じ「"/"の線で三角形を描く」ことを繰り返すときは、雛形として登録したPrototypeインスタンスから新しいインスタンスをクローンして流用してやれば良い。

概念図

concept.cld.jpg

  • Clientは Prototypeを呼び出す
  • Prototypeを実装したConcretePrototypeが、createCloneによってクローンされる

実装 図形描画

登場人物

  • frameworkパッケージ
    • Productインターフェース: Cloneableを継承
    • Managerクラス: CloneableをMapで格納、クローンを作成
  • entityパッケージ
    • Main: エントリポイント
    • MessageBoxクラス: Productを実装。四角形を描画 / ConcreteProduct
    • UnderLinePenクラス: Productを実装。下線を描画 / ConcreteProduct

実装 ソース

Product

Product
package prototype.product.frameworks;

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

}

Manager

package prototype.product.frameworks;

import java.util.HashMap;

public class Manager {

    private HashMap<String, Cloneable> showcase = new HashMap<>();
    public void register(String name, Cloneable prototype) {
        showcase.put(name, prototype);
    }

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

}

MessageBox

package prototype.product.entity;

import prototype.product.frameworks.Product;

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+4; 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 product = null;
        try {
            product= (Product)clone();
        }catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return product;
    }
}

UnderLinePen

package prototype.product.entity;

import prototype.product.frameworks.Product;

public class UnderLinePen implements Product{
    private char ulChar;
    public UnderLinePen(char ulChar) {
        this.ulChar = ulChar;
    }
    @Override
    public void use(String s) {
        int length = s.getBytes().length;
        System.out.println("¥ "+s+" ¥");
        for (int i = 0; i < length+4; i++) {
            System.out.print(ulChar);
        }
        System.out.println("");
    }

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

}

Main

package prototype.product.entity;

import prototype.product.frameworks.Manager;
import prototype.product.frameworks.Product;

public class Main {
    public static void main(String[] args) {
        Manager manager = new Manager(); 
        UnderLinePen linePen = new UnderLinePen('x'); //1
        MessageBox mbox = new MessageBox('*'); //1 
        MessageBox sbox = new MessageBox('/'); //1
        manager.register("強調メッセージ", linePen);// 2
        manager.register("警告ボックス",mbox); //2
        manager.register("斜めボックス    ", sbox);  //2

//      生成
        Product p1 = manager.create("強調メッセージ");//3
        p1.use("Hello world");   //4
        Product p2 = manager.create("警告ボックス"); //3
        p2.use("Hello world");   //4
        Product p3 = manager.create("斜めボックス "); //3
        p3.use("Hello world");   //4
    }
}

実行結果

¥ Hello world ¥
xxxxxxxxxxxxxxx
***************
* Hello world *
***************
///////////////
/ Hello world /
///////////////

解釈

  1. ConcreteProductに描画する文字を設置
  2. ManagerのHashMapにConcreteProduct達を登録
  3. Manager.createでクローンを生成 → Product.createCloneが自身のクローンを返す
  4. Product.useで描画

実装 クラス図

classes.cld.jpg

  • ProductがPrototypeの役割
  • MessageBox, UnderLinePenがConcretePrototypeの役割
  • ManagerがClientの役割

引用

増補改訂版 Java言語で学ぶデザインパターン入門 | 結城 浩 | コンピュータ・IT | Kindleストア | Amazon

6. Prototype パターン | TECHSCORE(テックスコア)

sayuen0
3年目プログラマ
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away