[書評・読書メモ] 「アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座」でデザインパターンの基本5パターンを学ぶ
読書メモと写経。
「オブジェクト指向言語でよく使われるデザインパターンのうち基本5パターンを覚えなさい。」とのこと。
- ステート/ストラテジー (State/Strategy)
- ファクトリーメソッド (Factory Method)
- アダプター (Adapter)
- コンポジット (Composite)
- テンプレートメソッド (Template Method)
実際は6つ。
売り上げランキング: 75,594
Contents
Strategy
ストラテジーパターンは、戦略(ストラテジー)により振る舞いを切り替えます。この切り替えには継承を利用することで、振る舞いの異なるオブジェクトを同じように利用できるようにします。呼び出し側のプログラムを変更することなく、呼び出される側のオブジェクトを切り替えることで、動作を切り替えることができます。
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.980-982). 株式会社 翔泳社. Kindle 版.
実際には、複雑な業務手順を入れ替えたりするときに、このストラテジーパターンは使われます。例えば、データを画面に表示させる手順と、プリンタに印刷させる手順を入れ替えるような場合です。
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1013-1015). 株式会社 翔泳社. Kindle 版.
参考資料
- Strategy パターン – デザインパターン入門 – IT専科 … 一連のアルゴリズム(戦略)をカプセル化(部品化)し、動的なアルゴリズムの切替えを可能とします。
State
オブジェクトの振る舞いに注目したストラテジーパターンとは異なり、ステートパターンは状態を表すためにオブジェクトを利用します。
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1019-1020). 株式会社 翔泳社. Kindle 版.
ここで重要なのは同じ社員であっても、役職という状態(ステート)を変えるだけでそれに対応して給料計算という振る舞いが変えられるということです。ステートパターンは状態の変化とそれに伴う変化をオブジェクトとして捉えているところが重要です。
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1046-1048). 株式会社 翔泳社. Kindle 版.
参考資料
- State パターン – デザインパターン入門 – IT専科 … 状態を表すオブジェクトを用意し、内包するその状態オブジェクトを切り替えることにより、処理内容(振る舞い)を変えられるようにします。
Factory Method
ステート/ストラテジーパターンでは、使用するクラスを切り替えることで振る舞いや状態を変えることができるように設計しました。ファクトリーメソッドパターンは使用するファクトリーを切り替えることで生成するインスタンスを切り替えます。
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1050-1052). 株式会社 翔泳社. Kindle 版.
# ShainFactory class from lesson 4.4
class ShainFactory
def create(type, kihonkyu)
shain = nil
if type == 'Tanto'
shain = Tanto.new(kihonkyu)
elsif type == 'Shunin'
shain = Shunin.new(kihonkyu)
end
shain
end
end
# ShainFactory class, meta programing version from lesson 4.4
class ShainFactory
def create(type, kihonkyu)
eval "#{type}.new(#{kihonkyu})", binding, __FILE__, __LINE__
end
end
参考資料
- Factory Method パターン – デザインパターン入門 – IT専科 … 実際に生成するオブジェクトに依存しない、オブジェクト生成のインタフェースを提供します。
Adapter
アダプターパターンは既に存在しているコードと新しく作られるコードをつなぎ合わせて再利用するためのパターンです。
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1070-1071). 株式会社 翔泳社. Kindle 版.
まとめると、Ruby では Adapter クラスを作らずとも同等の機能を実現できる手法もある、という事らしい。
- 変更の頻度が高くないと予想 -> 直接クラスに変更を加える。
- とりあえずの実装 -> モンキーパッチを当てて挙動を見る。
- 今後の変更が予測できない -> 安全策で委譲(has a 関係)を利用したアダプターパターンを使う。
以下などを基準にどんな手法を使うか判断する。
- カプセル化が必要かどうか
- 変更の頻度が高いか低いか
- 実装についてのコストがどれだけ違うか
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1134-1139). 株式会社 翔泳社. Kindle 版.
以下のコードを用意、実行。
[1] pry(main)> require_relative './hakenmoto/hakenshain'
=> true
[2] pry(main)> hakenshain = Hakenshain.new
=> #<hakenshain:0x00007f95f29145f8>
[3] pry(main)> hakenshain.kiritsu
派遣社員は元気に立ち上がりました。
=> nil
直接クラスを変更
[1] pry(main)> require_relative './hakenmoto/hakenshain'
=> true
[2] pry(main)> hakenshain = Hakenshain.new
=> #<hakenshain:0x00007f95f29145f8>
[3] pry(main)> hakenshain.standup
派遣社員は元気に立ち上がりました。
=> nil
オープンクラス(モンキーパッチ)
既存のクラスに対して、メソッドを追加したり書き換えたりすることをオープンクラスと呼ぶ。
[1] pry(main)> require_relative './hakenmoto/hakenyobidashi'
=> true
[2] pry(main)> hakenshain = Hakenshain.new
=> #<hakenshain:0x00007fff35a27da8>
[3] pry(main)> hakenshain.standup
派遣社員は元気に立ち上がりました。
=> nil
委譲(has a 関係)を利用したアダプターパターン
GoF Rubyデザインパターンでは設計原則として、継承よりも委譲のほうが好ましいと何度も書かれています。 なぜなら、継承はクラス同士の結合度が上がってしまうからです。
継承(is a 関係)
デメリットは、全てのメソッドを継承していること。
これも4.5.1と同じくカプセル化が不十分。
クラスとクラスの関係が強すぎるため、影響範囲が広くなり変更に弱くなってしまう。
[1] pry(main)> require_relative './ukeireshain'
=> true
[2] pry(main)> shain = Ukeireshain.new
=> #<ukeireshain:0x00007fd2f4159018>
[3] pry(main)> shain.standup
派遣社員は元気に立ち上がりました。
=> nil
委譲(has a 関係)
本来そのクラスが果たすべき役割を他のクラスに任せるようなやり方を「委譲」という。
関係が密接になりすぎることがないので、変更の影響は受けにくくなる。
デメリットは、継承のようにクラスの機能をそのまま引き継げないこと。
[1] pry(main)> require_relative './tsuyakushain'
=> true
[2] pry(main)> shain = Tsuyakushain.new
=> #<tsuyakushain:0x00007f9abf0c02b8 @gyoumu=#<gyoumu:0x00007f9abf0c0290>, @yakushoku=#<yakushoku:0x00007f9abf0c0268>>
[3] pry(main)> shain.standup
派遣社員は元気に立ち上がりました。
=> nil
[4] pry(main)> shain.calculate_salary(100)
=> 100
参考資料
- Adapter パターン – デザインパターン入門 – IT専科 … 互換性のないインタフェースを持つクラス同士の接続を可能にします。
- Rubyデザインパターン 6日目 : Adapter – Qiita
Composite
同じような構造を持つクラスが階層を作るような場合が、このパターンの出番です。
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1187). 株式会社 翔泳社. Kindle 版.
要追加調査。
参考資料
- Composite パターン – デザインパターン入門 – IT専科 … 個々のオブジェクトと合成したオブジェクトを同一視することにより、再帰的な構造を表現します。
Template Method
テンプレートメソッドのテンプレートとは、いろんな文書のひな形をそう呼ぶように、いろいろなクラスで共通して使う部分をあらかじめ作っておくことです。
長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1204-1206). 株式会社 翔泳社. Kindle 版.
参考資料
- Template Method パターン – デザインパターン入門 – IT専科 … スーパークラスで処理の流れを定義し、その処理の詳細はサブクラスで定義します。
所感
他の書籍も読みたい。
補遺
6章は、Rails。
7章は、関数型プログラミング。
7章に関して調べた追加情報。