@nqounetです。
「PerlとMooでモンスター軍団を量産してみよう」シリーズの最終回です。
前回の振り返り
前回は、Storable::dclone()を使って「深いコピー」を実装し、ネストしたオブジェクトも完全に独立したコピーを作る方法を学びました。
今回は、これまで作ってきたものがPrototypeパターンというデザインパターンであることを明かします。
シリーズ全体の目次は以下をご覧ください。
シリーズ全体を振り返る
これまでの6回を通じて、以下のことを学んできました。
| 回 | テーマ | 学んだこと |
|---|---|---|
| 第1回 | new()の限界 | 同じオブジェクトを大量に作るとコードが冗長に |
| 第2回 | clone()の導入 | MooX::Cloneで既存オブジェクトをコピー |
| 第3回 | バリエーション作成 | clone()後に属性を変更して派生を作成 |
| 第4回 | 浅いコピーの罠 | ネストしたオブジェクトが共有される問題 |
| 第5回 | 深いコピー | Storable::dclone()で完全に独立したコピー |
| 今回 | パターンの正体 | これがPrototypeパターンだった! |
実は、これらはすべてPrototypeパターンを学ぶための布石でした。
Prototypeパターンとは
Prototypeパターンは、GoF(Gang of Four)デザインパターンの一つで、「生成パターン」に分類されます。
既存のオブジェクト(プロトタイプ)を複製(clone)することで、新しいオブジェクトを生成するパターン
コンストラクタ(new)を直接呼び出す代わりに、既存のオブジェクトをコピーして新しいオブジェクトを作るというアプローチです。
パターンの構成要素
Prototypeパターンは、以下の構成要素から成り立っています。
| |
| 構成要素 | 役割 | 本シリーズでの対応 |
|---|---|---|
| Prototype | clone()メソッドを要求するインターフェース(Role) | Cloneableロール(概念上) |
| ConcretePrototype | clone()を実装した具象クラス | Monster, Weapon |
| Client | プロトタイプをclone()して新オブジェクトを作るコード | メインスクリプト |
Factory Methodパターンとの違い
同じ「生成パターン」に分類されるFactory Methodパターンと比較してみましょう。
| 項目 | Prototypeパターン | Factory Methodパターン |
|---|---|---|
| 生成方法 | 既存オブジェクトのクローン | newでインスタンス化 |
| クラス階層 | 不要(クローンするだけ) | サブクラス化が必要 |
| 状態の引き継ぎ | 元オブジェクトの状態を継承 | 新規に状態を設定 |
| 適用場面 | 生成コストが高い、動的決定、テンプレートからの派生 | 製品種類が固定、継承で拡張 |
| Perl実装 | clone() + MooX::Clone / Storable::dclone() | extends + オーバーライド |
コードで比較
Prototypeパターン(本シリーズで学んだ方法):
| |
Factory Methodパターン:
| |
Prototypeパターンは「既存オブジェクトをコピーする」のに対し、Factory Methodパターンは「ファクトリクラスがnew()でオブジェクトを作る」という違いがあります。
Prototypeパターンが有効な場面
Prototypeパターンは、以下の場面で特に有効です。
生成コストが高いオブジェクト
- 初期化に時間がかかるオブジェクトは、一度作ってコピーしたほうが効率的
実行時に動的にオブジェクト種類を決定する
- コンパイル時にどのクラスを使うか分からない場合、既存オブジェクトをコピーして対応
テンプレートからのバリエーション生成
- ベースオブジェクトを作り、少しずつ属性を変えたバリエーションを量産(本シリーズの主題)
複雑な初期化処理を回避したい
- 設定済みオブジェクトをコピーすれば、初期化ロジックを再実行する必要がない
Moo::Roleで明示的にPrototypeを表現する
概念をより明確にするため、Roleを使ってclone()を強制するインターフェースを定義することもできます。
| |
Cloneableロールがclone()メソッドを要求することで、「このクラスはPrototypeパターンに従っている」ことを明示できます。
シリーズのまとめ
このシリーズを通じて、以下のことを学びました。
技術的な学び
- MooX::CloneでMooクラスに
clone()メソッドを追加できる clone()でオブジェクトを複製し、効率的に量産できる- 浅いコピーではネストしたオブジェクトが共有される問題がある
- Storable::dclone()で深いコピーを実装し、完全に独立したコピーを作れる
パターン的な学び
- 既存オブジェクトをコピーして新しいオブジェクトを作る手法は「Prototypeパターン」である
- Prototypeパターンは GoF デザインパターンの「生成パターン」の一つである
- Factory Methodとは異なり、クラス階層を必要としない柔軟なアプローチである
発展的な学習
このシリーズを終えた後、さらに以下のパターンを学んでみることをお勧めします。
- Abstract Factoryパターン: 関連するオブジェクト群を一括で生成
- Builderパターン: 複雑なオブジェクトを段階的に構築
- Flyweightパターン: メモリ効率を重視したオブジェクト共有
これらを学ぶことで、デザインパターンの理解がより深まるでしょう。
参考資料
謝辞
最後までお読みいただきありがとうございました。このシリーズが、皆さんのPerlプログラミングとデザインパターンの学習に役立てば幸いです。
次のシリーズもお楽しみに!
