如何使用Ruby Observer方法同时更新两个参数?

时间:2016-09-28 18:29:17

标签: ruby design-patterns

我正在研究Ruby的Design Pattern并且遇到了Observer方法。我试图自定义我自己的观察者方法来帮助我理解它,但它返回一个错误。以下是我提出的建议:

class YummyTastyDonut
    def update(changed_order)
        puts "Kitchen: Yo, change the order to #{changed_order.order}!"
        puts "Front: Order for #{changed_order.name}!"
        puts "Front: The price will now be #{changed_order.order_price} "
    end
end


class Customer
    attr_reader :name, :order
    attr_accessor :order_price

    def initialize(name, order, order_price)
        @name = name
        @order = order
        @order_price = order_price
        @observers = []
    end

    def order=(new_order, new_price)
        @order = new_order
        @order_price = new_price
        notify_observers
    end

    def notify_observers
        @observers.each do |observer|
            observer.update(self)
        end
    end

    def add_observer(observer)
        @observers << observer
    end

    def delete_observer(observer)
        @observers.delete(observer)
    end
end

如果你读过这本书,我改变了类名,但实质是一样的。我改变的一件事是order=方法;它现在接受两个参数而不是一个。

目标是,在创建新的Customer之后,我希望新客户能够更改我的订单并通知YummyTastyDonut。但是,我希望能够更新两件事:orderorder_price(显然,如果我更改订单,价格也会发生变化)。我希望YummyTastyDonut回应我的更改。

igg = Customer.new("Iggy", "Bacon Donut", 10)
=> #<Customer:0x0056212e48a940 @name="Iggy", @order="Bacon Donut", @order_price=10, @observers=[]>

donut = YummyTastyDonut.new
=> #<YummyTastyDonut:0x0056212e4894c8>

## Updating my order and order_price ##

   igg.order = ("yummy butter donut", 15)
#(repl):1: syntax error, unexpected ',', expecting ')'
#igg.order = ("yummy butter donut", 15)

如果我使用只接受一个参数的order=方法,它就会按预期工作。

def order=(new_order)
    @order = new_order
    notify_observers
end

 igg.order = "Triple bacon donut explosion"
Kitchen: Yo, change the order to Triple bacon donut explosion!
Front: Order for Iggy!
Front: The price will now be 10 

我需要更改哪些内容才能同时更新orderorder_price

2 个答案:

答案 0 :(得分:2)

赋值=用于接受要分配的单个参数。(或者在并行赋值的情况下,与变量的元素数相同)

你可以这样做:

def order=(args)
  @order = args[0]
  @order_price = args[1]
  notify_observers
end

然后像

一样打电话
igg.order=["yummy butter donut", 15]

或使用选项Hash作为@BartekGladys建议但是这两种解决方案看起来都很糟糕且容易错误,并且需要了解方法的内部以便正确使用它。

此外,即使这种方法有效,但是对于未来您或任何查看您的代码库的人来说都会非常混乱,因为您有一个实例变量@order所以假设order=(val)会分配该变量。

使用change_order接受orderorder_price的方法会更好,这样可以消除所有关于发生的混乱。

def change_order(new_order, new_price)
    @order = new_order
    @order_price = new_price
    notify_observers
end

然后阅读它也更有意义。

igg = Customer.new("Iggy", "Bacon Donut", 10)
#Currently seems like it is assigning order to an Array maybe? 
igg.order=("yummy butter donut", 15)
#New much clearer as to the implementation and purpose of changing an order
igg.change_order("yummy butter donut", 15)  

答案 1 :(得分:1)

这是一个非常奇怪的错误,但我找到了可以帮助你的解决方案。您可以使用一个参数并在那里包含2个值。

def order=(opts={})
    @order = opts[:new_order]
    @order_price = opts[:new_price]
    notify_observers
end

并调用此函数:

igg.order= {new_order: 'yumyy better donut', new_price: 15 }