islands5 blog

日々起こったことを共有したり、思ったこと、勉強したことを書いていくブログ。普段はRailsやAWSを活用したWeb系の開発をやってます。

【デザインパターン】RubyでDecoratorパターン

この記事は『Head Firstデザインパターン』の内容を自分なりにメモしたものです。 サンプルコードをrubyで書き換えたりしているので、玄人の方はぜひコメントを!! 僕のように初級者で気になった方はぜひ書籍の方を確認してみてください^^

コーヒーショップのシステム

そのコーヒーショップのメニューがとても少なければいいと思うのですが、たいていのコーヒーショップはトッピングの追加や細かいオプションの追加ができたりします。
最初の設計

f:id:fiveislands:20160904220137j:plain

継承元のフィールドにトッピングを入れる?入れないのBool値を持たせて、料金を計算する。

問題の発生

あたらしいトッピングが追加されるとどうする? トッピング2倍で!というケースに対応できない

Decoratorパターンで実装しなおす

f:id:fiveislands:20160904220602j:plain

トッピングがBeverageのフィールドを持って、自身のコストのみを追加する。

Rubyで書いた場合はこんな感じ

class Beverage

  def get_description
    raise "should implement get_description method"
  end

  def cost
    raise "should implement cost method"
  end

end

class CondimentDecorator < Beverage
end

class Espresso < Beverage

  def initialize
    @description = "エスプレッソ"
  end

  def get_description
    @description
  end

  def cost
    200
  end

end

class HouseBlend < Beverage

  def initialize
    @description = "ハウスブレンドコーヒー"
  end

  def get_description
    @description
  end

  def cost
    150
  end

end

class Mocha < CondimentDecorator
  def initialize beverage
    @beverage = beverage
  end

  def get_description
    "#{@beverage.get_description}, モカ"
  end

  def cost
    50 + @beverage.cost
  end
end

実行コードは以下

beverage = Espresso.new
puts "#{beverage.get_description}: #{beverage.cost}" #=> エスプレッソ: 200円
beverage = Mocha.new(beverage)
beverage = Mocha.new(beverage)
beverage = Mocha.new(beverage)
puts "#{beverage.get_description}: #{beverage.cost}" #=> エスプレッソ, モカ, モカ, モカ: 350円

Decoratorパターンの定義・特徴

デコレータパターンはオブジェクト上に付加的な責務を動的に付与します。デコレータは、サブクラス化の代替となる。柔軟な機能拡張手段を提供します。

一つのクラスを継承し、メインとオプションの方向で役割がわかれている
なんか再帰っぽいイメージ、メインの方は明確に返す値(最低限の値)を持っていて、オプションの方は自分が持ってるベースクラスを元にした返り値をもってる。
使い勝手の良さそうなパターンだなと思いました。

昔とても疑問に思っていたJavaのI/O周りの定型コード

BufferedReader r =
            new BufferedReader(new InputStreamReader(System.in));

ここらへんもデコレータパターンを使っているということを知って、なるほどと感じました。。。

参考文献

Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本

Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本