早とちりプログラマの失敗から学ぶデザインパターン(Factory Method:適用後)
このシリーズについて
このシリーズは
- 後先のことをなにも考えずに実装してしまう『早とちりプログラマ』
と
- すぐに仕様変更を加える『後出し上司』
のという魅力的な2人から、
デザインパターンの有用さを学んでいこうという素敵な企画です。
(早とちりプログラマのモデルは私です。。。)
要件
上司「コンサートでピアノが聴けるようにしてよ」
わたし「わっかりました〜!!!」
わたし「ピアノ以外もきっと対応してくれっていわれそうだな」
わたし「さて、どうするか。。。」
いろんな楽器に対応できるようポリモーフィズムを用いる
ポリモーフィズムは継承によるものとインターフェースによるものがありますが、
今回はインターフェースで実装します。
演奏できるというインターフェース
interface Playable { play(): void; }
ピアノクラス
class Piano implements Playable { public play(): void { console.log('ポロンポロン'); } }
コンサートクラス
class Concert { private instrument: Playable; constructor() { this.instrument = new Piano(); } public start(): void { this.instrument.play(); } }
Factory Methodを適用
わたし「このままだとConcertがPianoに依存しているから、
それをなんとかしたいな。。。Factory Method使ってみるか」
楽器生成クラス
class InstrumentFactory { static create(instrumentCode: string): Playable { if (instrumentCode === 'piano') { return new Piano(); } } }
コンサートクラス修正
class Concert { private instrument: Playable; constructor() { this.instrument = InstrumentFactory.create('piano'); } public start(): void { this.instrument.play(); } }
わたし「よし、これでConcertクラスから特定のクラスのnewが消えたな」
仕様変更
上司「クライアントがさ、やっぱりピアノじゃなくてギターじゃないとダメだって」
修正
ギタークラス
class Guitar implements Playable { public play() { console.log('ジャーン'); } }
楽器生成クラス追加
class InstrumentFactory { static create(instrumentCode: string): Playable { if (instrumentCode === 'piano') { return new Piano(); } else if (instrumentCode === 'guiltar') { return new Guitar(); } } }
コンサートクラス修正
class Concert { private instrument: Playable; constructor() { this.instrument = InstrumentFactory.create('guitar'); // 修正 } public start(): void { this.instrument.play(); } }
結果
呼び出す側の修正は、 楽器名を変えるだけでよくなりました。
デザインパターンを使用すると、記述量は増えますが、
既存のソースコードの書き直しが劇的に減ります(3箇所→1箇所)