Rubyによるデザインパターン5原則


# 概要

改めて基本を学ぶ。
[Rubyによるデザインパターン](http://www.amazon.co.jp/gp/product/4894712857/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4894712857&linkCode=as2&tag=kidachi-22)第1章。

# デザインパターンとは

- プログラミングにおいて繰り返し現れる問題に対する、適切解のパターン。
- 無駄無く設計されたオブジェクト指向プログラムの実現をサポート。

パターンとしてカタログ化されていることで
**車輪の再発明を防ぐ**


# デザインパターンの根底にある5つの考え

- 変わるものを変わらないものから分離する
- プログラムはインターフェイスに対して行う（実装に対して行わない）
- 継承より集約
- 委譲、委譲、委譲
- 必要になるまで作るな（YAGNI）


## 変わるものを変わらないものから分離する

ソフトウェアの仕様には必ず変更が加わるもの。
変わるものと変わらないものを分離しておくことで、
「仕様の変更」に対して「システムの変更」を出来る限り局所的にする。


## プログラムはインターフェイスに対して行う（実装に対して行わない）

可能な限り「一般的・抽象的なもの」に対してプログラミングすること。
（ここで言うインターフェイスは、Javaの組み込み構文としてのインターフェイスではなく、
より広いレベルで「抽象度を高めたもの」を意味する。）

これにより、全体のコードの結合度を下げる。


### 具体性が高く、密結合なコード


```ruby
if is_car?
  my_car = Car.new
  my_car.drive(200)
else
  my_plane = AirPlane.new
  my_plane.fly(200)
end
```

乗り物が増える度にコード全体に変更が必要（変更に弱い）。

### 抽象度が高く、疎結合なコード

```ruby
my_vehicle = get_vehicle
my_vehicle.travel(200)
```

乗り物の数が増えても本コードに変更を加える必要はない（変更に強い）。


## 継承より集約

継承は望ましくないつながりを作ってしまう。

具体的には

- サブクラスの振る舞いは、スーパークラスの振る舞いに依存する。
- サブクラスからスーパークラスの中身を覗くことが出来る。

```ruby
class Vehicle
  def start_engine
    # エンジンを動かすためのもろもろの処理..
  end

  def stop_engine
    # エンジンを止めるためのもろもろの処理..
  end
end

class Car < Vehicle
  def drive
    start_engine
    # driving..
    stop_engine
  end
end
```

- Carからエンジンの実装が丸見え
- エンジンを使用しない乗り物を作りたい場合は大改造が必要

#### →変わりやすい部分（Engine）を変わりにくい部分（Vehicle）から分離できていない。


### 代替案

**集約**を使う。
つまり、

#### オブジェクトに、「他のオブジェクトに対する参照」を持たせる。

オブジェクトが何かの一種である（is-a-kind-of）関係は避けて、
何かを持っている（has-a）関係にする。


#### Car has a Engineの例

```ruby
class Car
  def initialize
    @engine = Engine.new
  end

  def drive
    @engine.start
    # driving..
    @engine.stop
  end
end

class Engine
  def start
    # エンジンを動かすためのもろもろの処理..
  end

  def stop
    # エンジンを止めるためのもろもろの処理..
  end
end
```

これでEngineがVehicleから分離され、またカプセル化された。

これにより、Engineの手軽な切り替えが可能に。

```ruby
class Car
  def initialize
    @engine = GasolineEngine.new
  end

  def drive
    @engine.start
    # ガソリンエンジンでドライブ..
    switch_to_diesel
    # ディーゼルエンジンでドライブ..
    @engine.stop
  end

  def switch_to_diesel
    @engine = DieselEngine.new
  end
end
```


## 委譲、委譲、委譲

### 委譲（delegation）
（継承パターンと同じように）start_engineとstop_engineを
クラスの外に公開したいこともある。

そんな場合でも、処理の実態はEngineクラスに任せてしまう。

```ruby
class Car
  def initialize
    @engine = GasolineEngine.new
  end

  def drive
    @engine.start
    # driving..
    @engine.stop
  end

  def switch_to_diesel
    @engine = DieselEngine.new
  end

  def start_engine
    @eigine.start  # Engineクラスに任せる
  end

  def stop_engine
    @eigine.stop  # Engineクラスに任せる
  end
end
```

これで「継承より集約」を実現しつつ、継承時と同じ機能を持つクラスが作成できた。
つまり、

### 集約と委譲の組み合わせは、強力かつ柔軟な継承の代替手段。

※ start_engineやstop_engineは委譲のために書かなければならない無駄なコードに思えるが、
**method_missing**等の利用で解決できる。
これはProxyパターンで別途詳細する。


## 必要になるまで作るな（YAGNI／You Ain't Gonna Need It.）


#### 「将来使うかも」は、大抵使わない。

いたずらに柔軟性を持たせようとオーバーエンジニアリングして
コードの複雑性を増していては、本末転倒。

**デザインパターン自身は目的ではない。**
問題を解決し、目的を達成するための手段として役立てるべきであり、それ以上のものではない。


デザインパターンを考える上での戒め。



# 以上5原則を前提に

各パターンを見ていく。

【Template Method】-テンプレは準備した、あとはお好きに-
http://qiita.com/kidachi_/items/7c2a80bfc8a87a05051f

【Strategy】-取り替え可能パーツ群を戦略的に利用せよ-
http://qiita.com/kidachi_/items/02f8f6df955ba1d0e93b

【Observer】-本日のニュースをお届けします-
http://qiita.com/kidachi_/items/ce18d2a926c558159689

【Composite】 -世界は再帰的（部分は全体、全体は部分）-
http://qiita.com/kidachi_/items/6cb73b2bbc875e9bef6d

【Iterator】-君の子供たちに伝えたいのだけど-
http://qiita.com/kidachi_/items/afa4c6c29a6eb6be487a

その他WIP.