观察者模式的应用

最近想到一种电商中需求:用户可以关注某件商品,当该商品有降价或打折等促销活动的时候通知关注该商品的用户

这里有点类似于微博中关注某用户后,可以获取被专注用户的消息动态

这里我觉得可以用观察者模式来实现消息的传递

简化Demo代码如下

  1 # encoding: utf-8
  2 
  3 # 有三个角色 ("商品","买家","卖家")
  4 # 1.买家关注商品后商品出现价格变动的时候通知该买家
  5 # 2.买家可以设置当某个商品降价到一定程度的时候通知该买家
  6 # 3.卖家可以知道有多少人关注该商品
  7 
  8 # 通过数据库的实现方式
  9 # 1.新建五张张表,商品表,买家表(Buyers),卖家表,订阅发布表(Sub_pubs),消息表(Messages)(买家表和卖家表合意用一张用户表)
 10 # 2.当买家关注一个商品的时候向订阅发布表中写数据:(加入resource字段可以更好的适应可能出现的新的需求,例如:买家关注卖家后,买家可以得知卖家的一切动态等等)
 11 # {:pub_resource => 'product',
 12 #  :publisher_id => product.id,
 13 #  :sub_resource => 'buyer',
 14 #  :subscriber_id => buyer.id,
 15 #  :action => func}
 16 # 3.当商品价格变动后通过订阅发布表想消息表中写数据:
 17 # {:user_id => buyer.id,
 18 #  :message => 'some text'
 19 #  :state => 0}
 20 
 21 # 'notify_observer'将类似于这样
 22 def notify_observer # 不考虑高并发的情况
 23   Sub_pubs.where(id: self.id).each do |sub_pub|
 24     some_text = sub_pub.pub_resource.send(sub_pub.action, self)
 25     Message.create!(user_id: sub_pub.subscriber_id,
 26                     message: some_text.to_s,
 27                     state: 0)
 28   end
 29 end
 30 
 31 
 32 module Subject
 33   def initialize
 34     @observers = []
 35   end
 36 
 37   def add_observer ob
 38     unless @observers.include?(ob)
 39       @observers << ob
 40     end
 41   end
 42 
 43   def delete_observer ob
 44     @observers.delete ob
 45   end
 46 
 47   # 修改点1, 将发布消息调用的函数通过参数接收过来, 或者通过method_missing
 48   # 通知设置提醒的买家
 49   def notify_observer(func)
 50     @observers.each do |ob|
 51       if ob.state == 0
 52         ob.send(func, self)
 53       end
 54     end
 55   end
 56 
 57   def notify_remind_observer(func)
 58     @observers.each do |ob|
 59       if ob.state == 1
 60         ob.send(func, self)
 61       end
 62     end
 63   end
 64 
 65 end
 66 
 67 # 商品类
 68 class Product
 69   include Subject
 70   attr_reader :owner, :name, :price, :old_price
 71 
 72   def initialize(owner, name, price, discount)
 73     super()
 74     @owner = owner
 75     @name = name
 76     @price = price
 77     @old_price = ''
 78   end
 79 
 80   # 价格变动时发出通知:
 81   def price= new_price
 82     if @price != new_price
 83 
 84       old_price = @price.to_i
 85       @price = new_price
 86       @old_price = old_price
 87 
 88       @observers.each do |ob|
 89         if ob.remind_price >= new_price
 90           ob.state = 1
 91           notify_remind_observer(:remind_price_ok)
 92         end
 93       end
 94 
 95       if new_price < old_price
 96         # notify_observers_down_price
 97         notify_observer(:down_price)
 98         # 商品降价
 99       else
100         notify_observer(:up_price)
101         # 商品涨价
102       end
103 
104     end
105 
106   end
107 
108   # 折扣变动时发出通知
109   def discount= new_discount
110     old_discount = @discount
111     if new_discount != new_discount
112       @discount = new_discount
113       notify_observers
114       if new_discount >= 8
115         # 八折以上
116       else
117         # 八折以下
118       end
119     end
120   end
121 end
122 
123 # 管理类
124 module MethodManage
125   def down_price product
126     puts "#{product.owner.name}的#{product.name}提醒您: 商品降价了, 原价是 #{product.old_price},现价是 #{product.price}"
127   end
128 
129   def up_price product
130     puts "#{product.owner.name}的#{product.name}提醒您: 商品涨价了, 原价是 #{product.old_price},现价是 #{product.price}"
131   end
132 
133   def remind_price_ok product
134     puts "#{product.owner.name}的#{product.name}提醒您: 您可以购买#{product.name}了, 现价是 #{product.price}"
135   end
136 end
137 
138 class Buyers
139   include MethodManage
140   attr_accessor :name, :remind_price, :state
141   def initialize(name)
142     @name = name
143     @remind_price = -1
144     @state = 0
145   end
146 
147   # 关注商品后,商品价格发生变化通知购买者
148   def mark(resource)
149     @state = 0
150     resource.add_observer(self)
151     add_buyer(resource)
152   end
153 
154   # 设置提醒,当价格到达一定程度通知购买者
155   def remind(resource, price)
156     @state = 2
157     @remind_price = price
158     resource.add_observer(self)
159     add_buyer(resource)
160   end
161 
162   private
163   def add_buyer(product)
164     unless product.owner.buyers.include?(self)
165       product.owner.add_buyer(self)
166     end
167   end
168 end
169 
170 class Sellers
171   attr_reader :name, :buyers
172   def initialize(name)
173     @name = name
174     @buyers = []
175   end
176 
177   def add_buyer(buyer)
178     @buyers << buyer
179   end
180 end
181 
182 seller_jack = Sellers.new("jack")
183 apple = Product.new(seller_jack, 'Apple', '100', 1)
184 buyer_angel = Buyers.new('angel')
185 buyer_angel.mark(apple)
186 buyer_legend = Buyers.new('legend')
187 buyer_legend.remind(apple, 40)
188 apple.price = 101
189 apple.price = 30
190 p seller_jack.buyers
原文地址:https://www.cnblogs.com/angelfan/p/4311567.html