rubyでデザインパターン commandパターン

class Bulb
  def turnOn
    puts "電気がつきました"
  end

  def turnOff
    puts "真っ暗です"
  end
end

class Command
  def execute
  end

  def undo
  end

  def redo
  end
end

class TurnOn < Command
  def initialize(bulb)
    @bulb = bulb
  end

  def execute
    @bulb.turnOn
  end

  def undo
    @bulb.turnOff
  end

  def redo
    execute
  end
end

class TrunOff < Command
  def initialize(bulb)
    @bulb = bulb
  end

  def execute
    @bulb.turnOff
  end

  def undo
    @bulb.turnOn
  end

  def redo
    execute
  end
end

class RemoteControll
  def submit(command)
    @command = command.execute
  end
end

bulb = Bulb.new
turnOn = TurnOn.new(bulb)
turnOff = TrunOff.new(bulb)
remote_controll = RemoteControll.new
remote_controll.submit(turnOn)
remote_controll.submit(turnOff)
#出力
#電気がつきました
#真っ暗です

rubyでデザインパターン compositeパターン

あるオブジェクトの集合で構成されたオブジェクトも同一のインターフェースをもつパターンです。

class Employee

  attr_reader :salary, :name

  def initialize(name, salary)
    @name = name
    @salary = salary
  end

end

class Developer < Employee

  attr_reader :role

  def initialize(name, salary, role)
    super(name, salary)
    @role = role
  end
end

class Designer < Employee

  attr_reader :role

  def initialize(name, salary, role)
    super(name, salary)
    @role = role
  end
end

class Organization
  def initialize
    @Employees = []
  end

  def addEmployee(employee)
    @Employees << employee 
  end

  def salary
    @NetSalary = 0
    @Employees.each do |employee|
      @NetSalary = @NetSalary + employee.salary
    end
    @NetSalary
  end
end

John = Developer.new('John', 20, 'developer')
Aya = Designer.new('Aya', 18, 'designer')
organizatin = Organization.new

organizatin.addEmployee(John)
organizatin.addEmployee(Aya)

puts John.salary
puts Aya.salary
puts organizatin.salary

#出力
#20
#18
#38

rubyでデザインパターン adapterパターン

ライオンを狩るハンタークラスがあったのですが
急遽、野犬も狩るように言われてしまいました。
しかし、野犬はライオンとは別のインターフェイスを持っているので
このままではうまく使えません。
そこで野犬クラスを包み込んだようなadapterクラスを用意して中継する感じです。
このパターンは仕方なくって感じがしますね・・・
もちろん初めから野犬も狩猟の対象になることが分かっていたのなら野犬も同じインターフェイスを備えるべきです。

class Lion
  def roar
    
  end
end

class AfricanLion < Lion
  def roar
    "がおー"
  end
end

class Hunter
  def hunt(target)
    puts "ターゲットは#{target.roar}と威嚇している!"
  end
end

class WildDog
  def bark
    "わん"
  end
end

class WildDOgAdapter < Lion

  def initialize(dog)
    @dog = dog
  end

  def roar
    @dog.bark
  end
end

african_lion = AfricanLion.new

wild_dog = WildDog.new
wild_dog_adapter = WildDOgAdapter.new(wild_dog)

hunter = Hunter.new
hunter.hunt(african_lion)
hunter.hunt(wild_dog_adapter)

#出力
#ターゲットはがおーと威嚇している!
#ターゲットはわんと威嚇している!
#

rubyでデザインパターン decoratorパターン

class Coffee

  #価格
  def getCost
  end

  #商品説明
  def getDescription
  end
end

class SimpleCoffee < Coffee
  def getCost
    10
  end

  def getDescription
    'Simple coffee'
  end
end

class MilkCoffee < Coffee
  def initialize(coffee)
    @coffee = coffee
  end

  def getCost
    @coffee.getCost + 2
  end

  def getDescription
    "#{@coffee.getDescription}にミルクを加えました。"
  end
end

simple_coffee = SimpleCoffee.new
milk_coffee = MilkCoffee.new(simple_coffee)
puts simple_coffee.getCost
puts milk_coffee.getCost

puts simple_coffee.getDescription
puts milk_coffee.getDescription

#こうやって出力されます
#10
#12
#Simple coffee
#Simple coffeeにミルクを加えました。

このように基本はSimpleCoffeeだけど、ときどき機能を拡張するみたいな時に使えるパターン

Rubyでデザインパターン proxyパターン

class Door

  def open
    puts 'open door!'
  end

  def close
    puts 'close door!'
  end

end

class SecurityDoor

  def initialize(door)
    @door = door
  end

  def open(password)
    if password == 'open goma!'
      @door.open
    else
      puts 'password fail'
    end
  end

  def close(password)
    if password == 'close goma!'
      @door.close
    else
      puts 'password fail'
    end
  end

end


door = Door.new
security_door = SecurityDoor.new(door)

security_door.open('valid_password!')
security_door.open('open goma!')

DoorクラスをラップするSecurityDoorクラスを定義しています。
そこでパスワードを確認する処理を挟んで本来アクセスしたいであろうDoorクラスへのアクセスを制御しています。
ここがポイントでアクセス制御がproxyパターンの目的です。
場合によってはdecoratorパターンと実装がかなり似ることがありますが目的が違います。
proxyパターンの目的はアクセス制御
decoratorパターンの目的は機能の追加です。

Rubyによるオブジェクト指向 8章 コードサンプル

 
attr_reader :size, :parts

def initialize(args={})
 @size = args[:size]
 @parts = args[:parts]
end

def spares
 parts.spares
end

end

class Part
 attr_reader :name, :description, :needs_spares

 def initialize(args)
  @name = args[:name]
  @description = args[:description]
  @needs_spares = args.fetch(:needs_spares, true)
 end
end

class Parts
 attr_reader :parts

 def initialize(parts)
  @parts = parts
 end

 def spares
  parts.select { |part| part.needs_spares }
 end

end


chain = Part.new(name: "chain", description: "10-speed")
road_tire = Part.new(name: 'tire_size', description: "23")

road_parts = Parts.new([chain, road_tire])

road_bike = Bycycle.new(
size: 'L',
parts: road_parts
)

puts road_bike.size
puts road_bike.spares.size