Blog

Blog

PHODAL

一个python程序员的ruby三日游(四)——观察者模式

设计模式算是在OO中比较有趣的东西,特别是对于如我之类的用得不是很多的,虽然有时候也会用上,但是并不知道用的是怎样的模式。之前了解了几天的设计模式,实际上也就是将平常经常用到的一些东西进行了总结,如此而已,学习设计模式的另外一个重要的意义在于,我们使用了设计模式的时候我们会知道自己使用了,并且还会知道用了是怎样的设计模式。

至于设计模式这个东西和有些东西一样,是发现的而不是发明的,换句话说,我们可以将经常合到一起的几种模式用一个新的模式来命名,它是复合模式,但是也可以用别的模式来命名。

设计模式算是简化了我们在面向对象设计时候的诸多不足,这个在系统设计的初期有时候会有一定的作用,不过多数时候对于我来说,会用上他的时候,多半是在重构的时候,因为不是很熟悉。

观察者模式

观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作(Collaboration)。观察者模式是满足这一要求的各种设计方案中最重要的一种。

简单的来说,就是当我们监测到一个元素变化的时候,另外的元素依照此而改变。

Ruby观察者模式

Ruby中为实现Observer模式提供了名为observer的库,observer库提供了Observer模块。 其API如下所示 方法名 功 能 add_observer(observer) 添加观察者 delete_observer(observer) 删除特定观察者 delete_observer 删除观察者 count_observer 观察者的数目 change(state=true) 设置更新标志为真 changed? 检查更新标志 notify_observer(*arg) 通知更新,如果更新标志为真,调用观察者带参数arg的方法

Ruby观察者简单示例

这里要做的就是获取一个json数据,将这个数据更新出来。

获取json数据,同时解析。

require 'net/http'
require 'rubygems'
require 'json'

class GetData
  attr_reader:res,:parsed

  def initialize(uri)
    uri=URI(uri)
    @res=Net::HTTP.get(uri)
    @parsed=JSON.parse(res)
  end

  def id
    @parsed[0]["id"]
  end

  def sensors1
    @parsed[0]["sensors1"].round(2)
  end

  def sensors2
    @parsed[0]["sensors2"].round(2)
  end

  def temperature
    @parsed[0]["temperature"].round(2)
  end

  def led1
    @parsed[0]["led1"]
  end

end

下面这个也就是重点,和观察者相关的,就是被观察者,由这个获取数据。 通过changed ,同时用notify_observer方法告诉观察者

require 'rubygems'
require 'thread'
require 'observer'
require 'getdata'
require 'ledstatus'

class Led 
    include Observable

    attr_reader:data
    def initialize
        @uri='http://www.xianuniversity.com/athome/1'
    end
    def getdata
        loop do 
            changed()
            data=GetData.new(@uri)
            changed
            notify_observers(data.id,data.sensors1,data.sensors2,data.temperature,data.led1)
            sleep 1
        end
    end
end

然后让我们新建一个观察者

class LedStatus
  def update(arg,sensors1,sensors2,temperature,led1)
    puts "id:#{arg},sensors1:#{sensors1},sensors2:#{sensors2},temperature:#{temperature},led1:#{led1}"
  end
end

测试

require 'spec_helper'

describe LedStatus do
  let(:ledstatus){LedStatus.new()}

  describe "Observable" do
    it "Should have a result" do 
      led=Led.new
      led.add_observer(ledstatus)
      led.getdata
    end
  end

end

测试结果如下所示

phodal@linux-dlkp:~/tw/observer> rake
/usr/bin/ruby1.9 -S rspec ./spec/getdata_spec.rb ./spec/ledstatus_spec.rb
id:1,sensors1:22.0,sensors2:11.0,temperature:10.0,led1:0
id:1,sensors1:22.0,sensors2:11.0,temperature:10.0,led1:1
id:1,sensors1:22.0,sensors2:11.0,temperature:10.0,led1:0
id:1,sensors1:22.0,sensors2:11.0,temperature:10.0,led1:1
id:1,sensors1:22.0,sensors2:11.0,temperature:10.0,led1:1
id:1,sensors1:22.0,sensors2:11.0,temperature:10.0,led1:1

总结

使用Ruby自带的Observer库的优点是,让我们可以简化相互之间的依赖性。同时,也能简化程序的结构,相比于自己写observer的情况下。

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806

新书《全栈应用开发:精益实践》

这不是一本深入前端、后台、运维、设计、分析等各个领域的书籍。本书以实践的方式,将这一系列的领域及理论知识结合到一起,来帮助读者构建全栈Web 开发的知识体系,并辅以精益及敏捷的思想,来一步步开发Web 应用:从创建一个UI 原型到编写出静态的前端页面;从静态的前端页面到带后台的应用,并部署应用;从Web 后台开发API 到开发移动Web 应用。在这个过程中,我们还将介绍一些相辅相成的步骤:使用构建系统来加速Web 应用的开发;为应用添加数据分析工具来改进产品;使用分析工具来改善应用的性能;通过自动化部署来加快上线流程;从而帮助读者开发出一个真正可用的全栈 Web 应用。同时,我们也将帮助读者把这些步骤应用到现有的系统上,改进现有系统的开发流程。

comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Developer, Consultant, Writer, Designer

ThoughtWorks 高级咨询师

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 与我沟通

标签