具体的なケースとして以下が考えられる。
任意の処理を行うバッチプログラムを作成するためのクラス設計
- 基本クラス
- すべてのバッチプログラムに共通の処理(ログ出力)を実装し、ビジネスロジックについては各継承クラスに任せる。
- 継承クラスA
- ビジネスロジックとしてAという機能を実装
- 継承クラスB
- ビジネスロジックとしてBという機能を実装
変更要求
このクラス設計にしたがって開発を行った場合、次のような変更要求があると途端にクラス設計の美しさが損なわれる。- CおよびDという機能を実現するバッチを追加してほしい。また、これらのバッチは起動時にあるファイルをロックし、終了時にロックを解除する必要がある。
要求への対応
基本クラスへロック機能を追加すると、既存のプログラムに影響がでてしまうので下記いずれかが対応として考えられる。- 基本クラスにロック機能を追加した中間クラスを作成し、継承クラスCとDではこの中間クラスを継承する。
- ロック機能は別クラスに集約し、継承クラスCとDでは集約クラスのロック機能を利用する。
対応案の考察
- 1番目の方法は、基本クラスから始まる「実装を追加するための継承」という流れに「機能を追加するための継承」という流れを混ぜてしまう。
- 2番目の方法は、ロック機能とビジネスロジックの結合が強くなりがち。(やっぱロック機能いらないや、とか別のバッチにもロック機能つけて、とか言われた場合にビジネスロジックを含むクラスの修正が必要になってしまう)
さらに、Eという機能を実現するバッチを追加してほしい。また、このバッチの実行開始と終了時にEメールを送信してほしい。などと言われると余計面倒なことになる。
機能と実装の分離
このような場合に、Bridgeパターンに基づいて機能(を追加するための継承)と実装(を追加するための継承)を別の流れになるようなクラス設計にしておけば、変更要求に強い構造になる。- Abstraction
- 機能を追加する流れの最上位クラス。Implementorのインスタンスを保有する(=Bridge担当)
- Implementor
- 実装を追加する流れの最上位クラス
- Refined Abstraction
- 機能を追加する際にAbstractionを継承して作成するクラス。例で言うところのロック機能の追加はここで実装する。
- Concrete Implementor
- 実装を追加する際にImplementorを継承して作成するクラス。例で言うところの継承クラスA~Dはこれのこと。
0 件のコメント:
コメントを投稿