Prototype
-
原型となるインスタンスをコピーして新しいインスタンスを生成するパターン
- 親クラスでインスタンスをコピーするためのメソッドを定義し、子クラスで自分自身のコピーを返すように実装する
-
コピーには「浅いコピー」と「深いコピー」がある
- 浅いコピー
- 変数に格納された値がそのままコピーされる
- オブジェクトの参照を格納した変数では、参照がコピーされる →どちらかのオブジェクトを変更すると、もう片方も変更される
- 深いコピー
- オブジェクトの参照を格納した変数では、実体がコピーされる →どちらかのオブジェクトを変更しても、もう片方に影響を与えない
- 浅いコピー
-
「継承」と「ポリモーフィズム」を利用したパターン
PrototypeとConcretePrototypeクラスの間に継承(実装)関係Clientクラスでは親クラスであるPrototypeクラスで提供されているAPIのみを使ってプログラミングを行うClientクラスとConcretePrototypeに依存関係がないので、ConcretePrototypeの差し替えは追加・修正が可能(インターフェース分離の原則)
メリット・デメリット
メリット
- オブジェクトの生成処理を隠蔽できる
- 構築済みのプロトタイプのクローンの作成を使うことにより、初期化コードの重複を削減
- 利用者と具体的なクラスの結合度を弱められる
デメリット
- ディープコピーとシャローコピーの違いを理解していないと想定外のバグを発生させる恐れがある
用途
- クラスからのインスタンス生成が難しい場合
- ユーザー操作によって生成されたグラフィックオブジェクトなど
- 例)パワーポイントの図形のコピー
- インスタンス化のコストがコピーよりも高い場合
デザインパターンの種類
生成に関するデザインパターン
例(Mermaid)
Manager- コピーするオブジェクトを管理しつつ、インスタンスを要求された際にコピーを返す
Prototype- インターフェースもしくは抽象クラス
- インスタンスをコピーして新しいインスタンスを作るためのメソッドを定める
ConcretePrototypePrototypeを実装(継承)する子クラスPrototypeで定義されたコピー用のメソッドを実装する
classDiagram class Manager{ } class Prototype{ <<interface>> createCopy() } class ConcretePrototype{ createCopy() } Prototype <-- Manager Prototype <|.. ConcretePrototype
商品のコピーを行う場合
classDiagram class ItemManager { -items Record<string,ItemPrototype> registerItem(key string,item ItemPrototype) create(key string) } class ItemPrototype { <<abstract>> name string detail Object addComment() createCopy() ItemPrototype } class DeepCopyItem { createCopy():ItemPrototype } class ShallowCopyItem { createCopy():ItemPrototype } ItemPrototype <-- ItemManager ItemPrototype <|-- DeepCopyItem ItemPrototype <|-- ShallowCopyItem