zoukankan      html  css  js  c++  java
  • 观察者模式的应用

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

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

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

    简化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
  • 相关阅读:
    Winefish-GTK LaTeX 编辑器
    GPuTTY:SSH 会话治理器
    Zudeo──高清版 Youtube
    HardInfo-体系信息搜集对象
    Liferea 1.2.0 正式版
    HomeBank:家庭理财软件
    ParolaPass:暗码天生器
    VLC Media Player 0.8.6
    流程图的绘制方法
    Delphi 2009 中的匿名方法(reference to)
  • 原文地址:https://www.cnblogs.com/angelfan/p/4311567.html
Copyright © 2011-2022 走看看