第7章


Prototypeパターン(コピーしてインスタンスを作る)

「Prototype」とは?

通常、インスタンスを作成する場合には、クラス名を指定する。
しかし、クラス名を指定せずにインスタンスを作成したくなる場合がある。

その場合にはクラスからインスタンスを作るのではなく、
インスタンスをコピーして新しいインスタンスを作る。

このようなパターンをPrototypeパターンという

例としては以下のような場合があげられる。

種類が多すぎてクラスにまとめられない場合

扱うオブジェクトの種類が多すぎて、
1つ1つ別のクラスにしていたら、ソースファイルを多数作成する必要がある場合

クラスからのインスタンス生成が難しい場合

生成させたいインスタンスが複雑な過程を経て作られているものの場合。
例えば、グラフィック画dぃタなどでユーザがマウスの操作によって作り上げた図形を現すインスタンス。

フレームワークと生成するインスタンスを分けたい場合

インスタンスの生成を特定のフレームワークに依存させたくない場合。


Prototypeの具体例 (サンプルプログラム)

Productインターフェイス

<?php

interface Product {
   function show($string);
   function createClone();
}

?>

Managerクラス

<?php

class Manager {

    private $hashmap;

    public function __construct() {
        $this->hashmap = array();
    }

    public function register($name, $proto) {
        $this->hashmap[$name] = $proto;
    }

    public function create($protoname) {
        $product = $this->hashmap[$protoname];
        return $product->createClone();
    }
}

?>

Productインターフェイスを利用してインスタンスの複製を行うクラス。
$protoは実際のクラスはわからないが、
とにかくProductインターフェイスを実装したクラスのインスタンス。

※さきほどのProductインターフェイスやManagerクラスのソースに、
 インスタンスを作るクラスの名前が(後述するMessageBox?クラス、UnderlinePen?クラス)
 まったく出てきていない。  ソースの中にクラス名を書くと、そのクラスと密な関係が出来てしまう
 その点、このManagerクラスでは具体的なクラス名が出てこず
 Productというインターフェイス名だけを使っており、
 このインターフェイスだけがManagerクラスと他のクラスの架け橋になっている。

MessageBox?クラス

<?php

require_once("Product.class.php");

class MessageBox implements Product {

    private $decochar;

    public function __construct($decochar) {
        $this->decochar = $decochar;
    }

    public function show($string) {
        $length = strlen($string);

        for ($i = 0; $i < $length + 4; $i++) {
            echo $this->decochar;
        }

        echo "<br />";
        echo $this->decochar." ".$string." ".$this->decochar;
        echo "<br />";

        for ($i = 0; $i < $length + 4; $i++) {
            echo $this->decochar;
        }

        echo "<br />";
    }

    public function createClone() {
        $this_clone = clone $this;

        if (!($this_clone instanceof Product)) {
           throw new Exeception();
        }

        return $this_clone;
    }
}

?>

Productクラスのサブクラス。
なお、createCloneメソッドは、自身の複製を行うメソッド。

UnderlinePen?クラス

<?php

require_once("Product.class.php");

class UnderlinePen implements Product {

    private $ulchar;

    public function __construct($ulchar) {
        $this->ulchar = $ulchar;
    }

    public function show($string) {

        $length = strlen($string);
        echo " ".$string." ";
        echo "<br />";

        for ($i = 0; $i < $length; $i++) {
            echo $this->ulchar;
        }

        echo "<br />";
    }

    public function createClone() {

        $this_clone = clone $this;

        if (!($this_clone instanceof Product)) {
           throw new Exeception();
        }
        return $this_clone;
    }
}

?>

Productクラスのサブクラス。
なお、createCloneメソッドは、自身の複製を行うメソッド。


Mainクラス

<?php

require_once("Manager.class.php");
require_once("UnderlinePen.class.php");
require_once("MessageBox.class.php");

class Main {

    public function __construct() {

        $manager = new Manager();
        $upen = new UnderlinePen("~");
        $mbox = new MessageBox("*");
        $sbox = new MessageBox("/");

        $manager->register("strong message", $upen);
        $manager->register("warning box", $mbox);
        $manager->register("slash box", $sbox);

        $product1 = $manager->create("strong message");
        $product1->show("Hello, world.");
        echo "<br />";
        $product2 = $manager->create("warning box");
        $product2->show("Hello, world.");
        echo "<br />";
        $product3 = $manager->create("slash box");
        $product3->show("Hello, world.");

    }

:new Main();

?>

Prototypeパターンにでてくるもの

Prototype(原型)

インスタンスをコピーして新しいインスタンスを作るためのメソッドを定める。
サンプルプログラムではProductインターフェイスがこの役をつとめた。

ConcretePrototype?(具体的な原型)

インスタンスをコピーして新しいインスタンスを作るためのメソッドを実装する。

Client(利用者)

インスタンスをコピーして新しいインスタンスを作るメソッドを実装する。


Prototypeパターンの利点

最初にあげた例に照らし合わせてみると…

種類が多すぎてクラスにまとめられない場合

サンプルプログラムでは3つの雛型が登場した。
これらの雛型をもっと増やしても、プログラムのファイル数は変わらない。

フレームワークと生成するインスタンスを分けたい場合

サンプルプログラムでは、インスタンスのコピーを行う部分を
ManagerクラスとProductクラスに閉じ込めているので、これは実現している。

再利用性

ソースの中にクラス名がないので、再利用をしやすい


参考資料

  • Java言語で学ぶデザインパターン入門

最新の20件

2014-07-10 2014-06-07 2010-12-08 2010-11-12 2010-11-01 2010-10-25 2010-10-15 2010-08-18 2010-08-02 2010-07-20

今日の1件

  • 第7章(1)

  • counter: 298
  • today: 1
  • yesterday: 0
  • online: 1