返品処理という新しい種類の部品を足すと、ロールと3つの Factory の4ファイルを直すことになる。市場を足すのは軽く、部品の種類を足すのは重い理由から、Abstract Factory を使う条件を整理します。
手数料4%・ユーロ・フランス語通知の EU 向けを追加するとき、OrderProcessor も既存の Factory も製品クラスも書き換えない。新規ファイルを足すだけで済むこと(開放閉鎖原則)を確かめます。
注文処理を OrderProcessor クラスにまとめ、Factory をコンストラクタで外から渡す。呼び出し側の設定を変えるだけで国内用・海外用を切り替えられる、Moo での依存性注入(DI)を実装します。
海外向けの Factory を足して、国内用と海外用を差し替えるだけで製品のセットごと切り替える。呼び出し側が具体クラスを知らずに済む理由と、クラスが10個に増えた代わりに何が防げるかを整理します。
国内の注文に海外の決済が混ざる事故を、決済・配送・通知を1つの Factory からセットで作らせて防ぐ。Moo::Role で Factory の約束事を決め、国内向けから導入します(Abstract Factory)。
市場の判定を書き間違えて、国内の注文に海外の決済クラスが混ざる。手数料が3%でなく5%、円でなくドルで計算される事故を動かして確かめ、人の注意で防ぐ限界を見ます。
国内向けの注文フローに海外向けを足すと、クラスは3つから6つになり、市場を判定する if/else があちこちに広がる。分岐で切り替える作りがどこで苦しくなるかを確かめます。
ECサイトの注文処理を、決済・配送・通知の3クラスに分けて Perl と Moo で作る。国内向けだけの素直な実装から、のちに国別の組み合わせで困る連載を始めます。
Flyweightパターンを学ぶ全6回のシリーズ目次。弾幕シューティングを題材に、大量オブジェクトのメモリ効率化テクニックを習得します。
ここまでのコードを Flyweight パターンの役割(Flyweight・FlyweightFactory・Client、内部状態・外部状態)に対応づけます。共有する Flyweight と、複製する Prototype の違いを表とコードで比べ、使える場面も挙げます。
第4回までの BulletType・BulletFactory・render を、BattleField クラスに組み合わせます。spawn_radial と spawn_spiral で弾幕パターンを作り、画面外に出た弾は update で捨てる。68発を3種類の BulletType で動かす完成コードです。
BulletType の render は座標を引数で受け取ります。位置を持たないので、同じオブジェクトを複数の弾が共有できます。放射状に飛ぶ12発と、螺旋状の72発を、3つの BulletType で動かすターミナルのアニメーションを書きます。
BulletFactory の get は、キャッシュに無い種類だけ作り、あれば同じオブジェクトを返します。//= 演算子で書きます。1000発の弾が参照する BulletType は5つで、弾の配列は約245.8KB。第1回の約600KB と並べます。
形状・色・サイズを BulletType に切り出し、位置と速度だけを弾ごとのハッシュに残します。弾100発分は60.8KB から25.2KB になりました(BulletType 3つは別に2.1KB)。内部状態と外部状態という用語もここで押さえます。
Bullet クラスで同じ赤い丸の弾を作り、Devel::Size で測ると1発あたり約600バイト、1万発で約5.8MB でした。形状・色・サイズは全弾で同じなのに、弾ごとに持っている。共有できる属性と、弾ごとに違う属性を表で分けます。