Hatena::Grouprubyist

Going My Ruby Way このページをアンテナに追加 RSSフィード

Ruby ロゴ (C) Ruby Association LLC

2013年10月19日(土)

MVC

18:02 | MVC - Going My Ruby Way を含むブックマーク はてなブックマーク - MVC - Going My Ruby Way MVC - Going My Ruby Way のブックマークコメント

MVC について書かれている次の記事を読みました。

わかりやすく書かれていて面白かったです。

サンプルが Java で書かれていたので Ruby で書いてみました。

MVC0 (MVCじゃないコード)

#!/usr/bin/env ruby
# -*- coding: UTF-8 -*-
$KCODE = "UTF-8" if RUBY_VERSION < '1.9'

class Controller
  def initialize(model)
    @model = model
  end

  def sellListener
    @model.sell
    @model.view
  end
end

class ItemModel
  def initialize(name, price, stock)
    @name  = name
    @price = price
    @stock = stock
    view
  end

  def sell
    @stock -= 1
  end

  def view
    puts "商品名 = #{@name}"
    puts "価格   = #{@price}"
    puts "在庫数 = #{@stock}"
    puts ""
  end
end

if $0 == __FILE__
  model       = ItemModel.new("MVCモデル", 10000, 10)
  controller  = Controller.new(model)

  # 購入ボタンが押されたことを通知
  controller.sellListener
end

# vi:set ts=2 sw=2 ai:

MVC1 (コントローラが頑張る MVC)

#!/usr/bin/env ruby
# -*- coding: UTF-8 -*-
$KCODE = "UTF-8" if RUBY_VERSION < '1.9'

class Controller
  def initialize(model, view)
    @model = model
    @view  = view
  end

  def sellListener
    # 2. 在庫数を取得して、
    stock = @model.stock
    # 3. 減らした在庫数を更新
    @model.stock = stock - 1
    # 4. 購入されたことを通知
    @view.view
  end
end

class ItemModel
  def initialize(name, price, stock)
    @name  = name
    @price = price
    @stock = stock
  end

  attr_reader :name
  attr_reader :price
  attr_accessor :stock
end

class ItemView
  def initialize(model)
    @model = model
    view
  end

  def view
    # 5. 表示する在庫数を取得
    puts "商品名 = #{@model.name}"
    puts "価格   = #{@model.price}"
    puts "在庫数 = #{@model.stock}"
    puts ""
  end
end

if $0 == __FILE__
  model       = ItemModel.new("MVCモデル", 10000, 10)
  view        = ItemView.new(model)
  controller  = Controller.new(model, view)

  # 1. 購入ボタンが押されたことを通知
  controller.sellListener
end

# vi:set ts=2 sw=2 ai:

MVC1.5 (コントローラが少し頑張る MVC)

#!/usr/bin/env ruby
# -*- coding: UTF-8 -*-
$KCODE = "UTF-8" if RUBY_VERSION < '1.9'

class Controller
  def initialize(model, view)
    @model = model
    @view  = view
    # 初期状態を表示
    @view.view
  end

  def sellListener
    # 2. 購入されたことを通知
    @model.sell
    # 3. 購入されたことを通知
    @view.view
  end
end

class ItemModel
  def initialize(name, price, stock)
    @name  = name
    @price = price
    @stock = stock
  end

  attr_reader :name
  attr_reader :price
  attr_reader :stock

  def sell
    @stock -= 1
  end
end

class ItemView
  def initialize(model)
    @model = model
  end

  def view
    # 4. 表示する商品名、価格、在庫数を取得
    puts "商品名 = #{@model.name}"
    puts "価格   = #{@model.price}"
    puts "在庫数 = #{@model.stock}"
    puts ""
  end
end

if $0 == __FILE__
  model       = ItemModel.new("MVCモデル", 10000, 10)
  view        = ItemView.new(model)
  controller  = Controller.new(model, view)

  # 1. 購入ボタンが押されたことを通知
  controller.sellListener
end

# vi:set ts=2 sw=2 ai:

MVC2 (依存性での MVC)

#!/usr/bin/env ruby
# -*- coding: UTF-8 -*-
$KCODE = "UTF-8" if RUBY_VERSION < '1.9'

require 'observer'

class Controller
  def initialize(model)
    @model = model
  end

  def sellListener
    # 2. 購入されたことを通知
    @model.sell
  end
end

module ItemLogic
  def sell ; raise NotImplementedError ; end
end

module ItemSubject
  def add_observer(observer) ; raise NotImplementedError; end
  def notify_observers(event) ; raise NotImplementedError; end
  def name ; raise NotImplementedError; end
  def price ; raise NotImplementedError; end
  def stock ; raise NotImplementedError; end
end

class ItemModel
  include ItemLogic
  include ItemSubject
  include Observable

  def initialize(name, price, stock)
    @name  = name
    @price = price
    @stock = stock
  end

  attr_reader :name
  attr_reader :price
  attr_reader :stock

  def sell
    @stock -= 1

    # 3. モデルが変更されたことを通知
    changed ; notify_observers(self)
  end

  def add_observer(*)
    super

    changed ; notify_observers(self)
  end
end

class ItemView
  def update(model)
    @model = model
    view
  end

  def view
    # 4. 表示する商品名、価格、在庫数を取得
    puts "商品名 = #{@model.name}"
    puts "価格   = #{@model.price}"
    puts "在庫数 = #{@model.stock}"
    puts ""
  end
end

if $0 == __FILE__
  model       = ItemModel.new("MVCモデル", 10000, 10)
  view        = ItemView.new
  model.add_observer(view)
  controller  = Controller.new(model)

  # 1. 購入ボタンが押されたことを通知
  controller.sellListener
end

# vi:set ts=2 sw=2 ai:

どのスクリプトも実行結果は次のとおり。

$ ruby mvc2.rb 
商品名 = MVCモデル
価格   = 10000円
在庫数 = 10個

商品名 = MVCモデル
価格   = 10000円
在庫数 = 9個