コンセプト
プロトタイプ インスタンスを使用して、作成するオブジェクトの種類を指定し、これらのプロトタイプをコピーして新しいオブジェクトを作成します。
プロトタイプ プロトタイプ パターンは、作成方法の詳細を知らなくても、あるオブジェクトで別のカスタマイズ可能なオブジェクトを作成できるようにする創造的なデザイン パターンです。
仕組み
作成されるオブジェクトにプロトタイプ オブジェクトを渡すことにより、プロトタイプ オブジェクトに自身のコピーを要求することで、作成されるオブジェクトが作成されます。
それはどのような問題を解決しますか
それが直面する主な問題は、「複雑な構造を持ついくつかのオブジェクト」の作成です。要件の変更により、これらのオブジェクトはしばしば大幅な変更に直面しますが、比較的安定した一貫したインターフェイスを持っています。
Role
抽象プロトタイプ(Prototype)ロール:自身を複製するためのインターフェースを宣言
具象プロトタイプ(Concrete Prototype)ロール:自身を複製する操作を実装
構造図
コード
浅いコピーモード
ソースオブジェクトの参照アドレスなどをコピーして直接コピーすると、元の内容が変更され、新しい内容も変更されます。
<?php header('Content-type:text/html;charset=utf-8'); /** * PHP原型模式-潜拷贝 */ /** * Interface Prototype 抽象原型模式 */ interface Prototype { // 定义拷贝自身方法啊 public function copy(); } /** * Class ConcretePrototype 具体原型模式 */ class ConcretePrototype implements Prototype { private $name; public function __construct($name) { $this->name = $name; } public function setName($name) { $this->name=$name; } public function getName() { return $this->name; } /** * 拷贝自身 * * @return ConcretePrototype 返回自身 */ public function copy() { return clone $this;//浅拷贝 } } /** * 测试潜拷贝 */ class LatentCopyDemo{ public $array; } /** * Class Client 客户端 */ class Client{ /** * 测试方法 */ public static function test(){ $demo = new LatentCopyDemo(); $demo->array = array(1,2); $object1 = new ConcretePrototype($demo); $object2 = $object1->copy(); var_dump($object1->getName()); echo '<br/>'; var_dump($object2->getName()); echo '<br/>'; $demo->array = array(3, 4); var_dump($object1->getName()); echo '<br />'; var_dump($object2->getName()); echo '<br />'; } } Client::test();
実行結果
object(LatentCopyDemo)#1 (1) { ["array"]=> array(2) { [0]=> int(1) [1]=> int(2) } } object(LatentCopyDemo)#1 (1) { ["array"]=> array(2) { [0]=> int(1) [1]=> int(2) } } object(LatentCopyDemo)#1 (1) { ["array"]=> array(2) { [0]=> int(3) [1]=> int(4) } } object(LatentCopyDemo)#1 (1) { ["array"]=> array(2) { [0]=> int(3) [1]=> int(4) } }
ディープコピーモード
ディープコピーはシリアル化と逆シリアル化を通じてコピーを完了し、新しいコピーのコンテンツは元のコンテンツを完全にコピーします。元のコンテンツは変更されますが、新しいコンテンツは変更されません。
<?php header('Content-type:text/html;charset=utf-8'); /** * PHP原型模式-深拷贝 */ /** * Interface Prototype 抽象原型模式 */ interface Prototype { // 定义拷贝自身方法啊 public function copy(); } /** * Class ConcretePrototype 具体原型模式 */ class ConcretePrototype implements Prototype { private $name; public function __construct($name) { $this->name = $name; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } /** * 拷贝自身 * * @return ConcretePrototype 返回自身 */ public function copy() { $serialize_obj = serialize($this); $clone_obj = unserialize($serialize_obj); return $clone_obj; } } /** * 测试潜拷贝 */ class DeepCopyDemo{ public $array; } /** * Class Client 客户端 */ class Client{ /** * 测试方法 */ public static function test(){ $demo = new DeepCopyDemo(); $demo->array = array(1,2); $object1 = new ConcretePrototype($demo); $object2 = $object1->copy(); var_dump($object1->getName()); echo '<br/>'; var_dump($object2->getName()); echo '<br/>'; $demo->array = array(3, 4); var_dump($object1->getName()); echo '<br />'; var_dump($object2->getName()); echo '<br />'; } } Client::test();
走行結果
object(DeepCopyDemo)#1 (1) { ["array"]=> array(2) { [0]=> int(1) [1]=> int(2) } } object(DeepCopyDemo)#4 (1) { ["array"]=> array(2) { [0]=> int(1) [1]=> int(2) } } object(DeepCopyDemo)#1 (1) { ["array"]=> array(2) { [0]=> int(3) [1]=> int(4) } } object(DeepCopyDemo)#4 (1) { ["array"]=> array(2) { [0]=> int(1) [1]=> int(2) } }
メリットとデメリット
利点
1. 実行時にプロダクトを追加および削除できます
2. 新しいオブジェクトを指定するために値を変更できます
4. 使用するサブクラスの構築を削減します。
欠点
プロトタイプ パターンの主な欠点は、各クラスにクローン メソッドを装備する必要があることです。さらに、このクローン作成方法は、クラスの機能を総合的に考慮する必要があります。これは、新しいクラスの場合は難しくありませんが、既存のクラスを変換するのは必ずしも簡単ではありません。
適用可能なシナリオ
システムをその製品とは独立して作成、構成、表現する必要がある場合には、プロトタイプ パターンを使用します
動的読み込みなど、インスタンス化されるクラスが実行時に指定される場合
ファクトリの作成時を回避するにはクラス階層は製品クラス階層と同じです。
クラスのインスタンスが複数の異なる状態の組み合わせのうち 1 つだけを持つことができる場合。毎回適切な状態でクラスを手動でインスタンス化するよりも、対応する数のプロトタイプを作成してクローンを作成する方が便利かもしれません