[書評・読書メモ] 「アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座」でデザインパターンの基本5パターンを学ぶ

読書メモと写経。

[markdown]
「オブジェクト指向言語でよく使われるデザインパターンのうち基本5パターンを覚えなさい。」とのこと。

1. ステート/ストラテジー (State/Strategy)
2. ファクトリーメソッド (Factory Method)
3. アダプター (Adapter)
4. コンポジット (Composite)
5. テンプレートメソッド (Template Method)

実際は6つ。

## Strategy

> ストラテジーパターンは、戦略(ストラテジー)により振る舞いを切り替えます。この切り替えには継承を利用することで、振る舞いの異なるオブジェクトを同じように利用できるようにします。呼び出し側のプログラムを変更することなく、呼び出される側のオブジェクトを切り替えることで、動作を切り替えることができます。
>
> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.980-982). 株式会社 翔泳社. Kindle 版.

– [Add: lesson 4.2 · DriftwoodJP/sandbox-ruby-class@61b2b6d](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/61b2b6d8641cb198f99b74345143f16bdf4400ba)

> 実際には、複雑な業務手順を入れ替えたりするときに、このストラテジーパターンは使われます。例えば、データを画面に表示させる手順と、プリンタに印刷させる手順を入れ替えるような場合です。
>
> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1013-1015). 株式会社 翔泳社. Kindle 版.

### 参考資料

– [Strategy パターン – デザインパターン入門 – IT専科](http://www.itsenka.com/contents/development/designpattern/strategy.html) … 一連のアルゴリズム(戦略)をカプセル化(部品化)し、動的なアルゴリズムの切替えを可能とします。

## State

> オブジェクトの振る舞いに注目したストラテジーパターンとは異なり、ステートパターンは状態を表すためにオブジェクトを利用します。
>
> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1019-1020). 株式会社 翔泳社. Kindle 版.

– [Add: lesson 4.3 · DriftwoodJP/sandbox-ruby-class@2e985a8](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/2e985a8560e37a7710d62186576cbd9c89a8e9f9)

> ここで重要なのは同じ社員であっても、役職という状態(ステート)を変えるだけでそれに対応して給料計算という振る舞いが変えられるということです。ステートパターンは状態の変化とそれに伴う変化をオブジェクトとして捉えているところが重要です。
>
> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1046-1048). 株式会社 翔泳社. Kindle 版.

### 参考資料

– [State パターン – デザインパターン入門 – IT専科](http://www.itsenka.com/contents/development/designpattern/state.html) … 状態を表すオブジェクトを用意し、内包するその状態オブジェクトを切り替えることにより、処理内容(振る舞い)を変えられるようにします。

## Factory Method

> ステート/ストラテジーパターンでは、使用するクラスを切り替えることで振る舞いや状態を変えることができるように設計しました。ファクトリーメソッドパターンは使用するファクトリーを切り替えることで生成するインスタンスを切り替えます。
>
> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1050-1052). 株式会社 翔泳社. Kindle 版.

– [Add: lesson 4.4 · DriftwoodJP/sandbox-ruby-class@08fdeb1](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/08fdeb16bf9829450de839855d2b86f5cc1c7066)

“`ruby:shain_factory.rb
# 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
“`

“`ruby:shain_factory.rb
# 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専科](http://www.itsenka.com/contents/development/designpattern/factory_method.html) … 実際に生成するオブジェクトに依存しない、オブジェクト生成のインタフェースを提供します。

## Adapter

> アダプターパターンは既に存在しているコードと新しく作られるコードをつなぎ合わせて再利用するためのパターンです。
>
> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1070-1071). 株式会社 翔泳社. Kindle 版.

まとめると、Ruby では Adapter クラスを作らずとも同等の機能を実現できる手法もある、という事らしい。

1. 変更の頻度が高くないと予想 -> 直接クラスに変更を加える。
2. とりあえずの実装 -> モンキーパッチを当てて挙動を見る。
3. 今後の変更が予測できない -> 安全策で委譲(has a 関係)を利用したアダプターパターンを使う。

以下などを基準にどんな手法を使うか判断する。

– カプセル化が必要かどうか
– 変更の頻度が高いか低いか
– 実装についてのコストがどれだけ違うか

> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1134-1139). 株式会社 翔泳社. Kindle 版.

以下のコードを用意、実行。

– [Add: lesson 4.5 · DriftwoodJP/sandbox-ruby-class@6732f22](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/6732f221be957d2c9b162f8231e958cc16e08f92)

“`prettyprinted
[1] pry(main)> require_relative ‘./hakenmoto/hakenshain’
=> true
[2] pry(main)> hakenshain = Hakenshain.new
=> #
[3] pry(main)> hakenshain.kiritsu
派遣社員は元気に立ち上がりました。
=> nil
“`

### 直接クラスを変更

– [Add: lesson 4.5.1 · DriftwoodJP/sandbox-ruby-class@b5a8e47](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/b5a8e47da7af6d36b011b78a001de1682eac44e5)

“`prettyprinted
[1] pry(main)> require_relative ‘./hakenmoto/hakenshain’
=> true
[2] pry(main)> hakenshain = Hakenshain.new
=> #
[3] pry(main)> hakenshain.standup
派遣社員は元気に立ち上がりました。
=> nil
“`

– [クラス/メソッドの定義 (Ruby 2.4.0)](https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#alias)

### オープンクラス(モンキーパッチ)

既存のクラスに対して、メソッドを追加したり書き換えたりすることをオープンクラスと呼ぶ。

– [Add: lesson 4.5.2 · DriftwoodJP/sandbox-ruby-class@6207ab7](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/6207ab71118685e88b9b33af434c6b9d65028fbc)

“`prettyprinted
[1] pry(main)> require_relative ‘./hakenmoto/hakenyobidashi’
=> true
[2] pry(main)> hakenshain = Hakenshain.new
=> #
[3] pry(main)> hakenshain.standup
派遣社員は元気に立ち上がりました。
=> nil
“`

– [Rubyのオープンクラス:猿のようにパッチを当てない方法](https://www.infoq.com/jp/articles/ruby-open-classes-monkeypatching)
– [RubyのRefinement(翻訳: 公式ドキュメントより)](https://techracho.bpsinc.jp/hachi8833/2017_03_23/37464)

### 委譲(has a 関係)を利用したアダプターパターン

> GoF Rubyデザインパターンでは設計原則として、継承よりも委譲のほうが好ましいと何度も書かれています。 なぜなら、継承はクラス同士の結合度が上がってしまうからです。
>
> [Rubyデザインパターン 2日目 : Strategy – Qiita](https://qiita.com/Momozono/items/08a947f598466175d5cd)

#### 継承(is a 関係)

デメリットは、全てのメソッドを継承していること。
これも4.5.1と同じくカプセル化が不十分。
クラスとクラスの関係が強すぎるため、影響範囲が広くなり変更に弱くなってしまう。

– [Add: lesson 4.5.3 · DriftwoodJP/sandbox-ruby-class@31f110d](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/31f110d82a07acb3301ac12828c2c0ffc1a36d3e)

“`prettyprinted
[1] pry(main)> require_relative ‘./ukeireshain’
=> true
[2] pry(main)> shain = Ukeireshain.new
=> #
[3] pry(main)> shain.standup
派遣社員は元気に立ち上がりました。
=> nil
“`

#### 委譲(has a 関係)

本来そのクラスが果たすべき役割を他のクラスに任せるようなやり方を「委譲」という。
関係が密接になりすぎることがないので、変更の影響は受けにくくなる。
デメリットは、継承のようにクラスの機能をそのまま引き継げないこと。

– [Add: lesson 4.5.4 · DriftwoodJP/sandbox-ruby-class@ca14417](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/ca14417e97b460798a95900c5aca9959576e1f85)

“`prettyprinted
[1] pry(main)> require_relative ‘./tsuyakushain’
=> true
[2] pry(main)> shain = Tsuyakushain.new
=> #, @yakushoku=#>
[3] pry(main)> shain.standup
派遣社員は元気に立ち上がりました。
=> nil
[4] pry(main)> shain.calculate_salary(100)
=> 100
“`

### 参考資料

– [Adapter パターン – デザインパターン入門 – IT専科](http://www.itsenka.com/contents/development/designpattern/adapter.html) … 互換性のないインタフェースを持つクラス同士の接続を可能にします。
– [Rubyデザインパターン 6日目 : Adapter – Qiita](https://qiita.com/Momozono/items/7078aa3923df19f5b5d6)

## Composite

> 同じような構造を持つクラスが階層を作るような場合が、このパターンの出番です。
>
> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1187). 株式会社 翔泳社. Kindle 版.

– [Add: lesson 4.6 · DriftwoodJP/sandbox-ruby-class@04c5693](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/04c5693a9c7965cd73c256be59b30638215fadc1)

要追加調査。

### 参考資料

– [Composite パターン – デザインパターン入門 – IT専科](http://www.itsenka.com/contents/development/designpattern/composite.html) … 個々のオブジェクトと合成したオブジェクトを同一視することにより、再帰的な構造を表現します。

## Template Method

> テンプレートメソッドのテンプレートとは、いろんな文書のひな形をそう呼ぶように、いろいろなクラスで共通して使う部分をあらかじめ作っておくことです。
>
> 長瀬 嘉秀; 小林 慎治; 大崎 瑶. アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座 (Kindle の位置No.1204-1206). 株式会社 翔泳社. Kindle 版.

– [Add: lesson 4.7 · DriftwoodJP/sandbox-ruby-class@49f03ec](https://github.com/DriftwoodJP/sandbox-ruby-class/commit/49f03eceeef2377c3fd3b23ed0964d28247cdec3)

### 参考資料

– [Template Method パターン – デザインパターン入門 – IT専科](http://www.itsenka.com/contents/development/designpattern/template_method.html) … スーパークラスで処理の流れを定義し、その処理の詳細はサブクラスで定義します。

## 所感

他の書籍も読みたい。

## 補遺

6章は、Rails。

> * [「アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座」の6章のソースコード。](https://github.com/DriftwoodJP/sandbox-rails-jinji)

7章は、関数型プログラミング。

> * [「アジャイル時代のオブジェクト脳のつくり方 Rubyで学ぶ究極の基礎講座」の7章のソースコード。](https://gist.github.com/DriftwoodJP/5f0421ce0dcbe54726ef114e8dd99a56)

7章に関して調べた追加情報。

> * [第5回 イテレータ](https://shugo.net/article/cmagazine/5th/)
> * [「関数型プログラミングって何?」日本語訳 – Okapies’ Archive](http://okapies.hateblo.jp/entry/2016/12/15/021550)

[/markdown]