一个python程序员的ruby三日游(四)——观察者模式
2013-12-01 10:42
423 查看
设计模式算是在OO中比较有趣的东西,特别是对于如我之类的用得不是很多的,虽然有时候也会用上,但是并不知道用的是怎样的模式。之前了解了几天的设计模式,实际上也就是将平常经常用到的一些东西进行了总结,如此而已,学习设计模式的另外一个重要的意义在于,我们使用了设计模式的时候我们会知道自己使用了,并且还会知道用了是怎样的设计模式。
至于设计模式这个东西和有些东西一样,是发现的而不是发明的,换句话说,我们可以将经常合到一起的几种模式用一个新的模式来命名,它是复合模式,但是也可以用别的模式来命名。(转载保留 Phodal's
Blog Phodal's zenthink)
设计模式算是简化了我们在面向对象设计时候的诸多不足,这个在系统设计的初期有时候会有一定的作用,不过多数时候对于我来说,会用上他的时候,多半是在重构的时候,因为不是很熟悉。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作(Collaboration)。观察者模式是满足这一要求的各种设计方案中最重要的一种。
简单的来说,就是当我们监测到一个元素变化的时候,另外的元素依照此而改变。
其API如下所示
获取json数据,同时解析。
下面这个也就是重点,和观察者相关的,就是被观察者,由这个获取数据。
通过changed ,同时用notify_observer方法告诉观察者
然后让我们新建一个观察者
测试
测试结果如下所示
至于设计模式这个东西和有些东西一样,是发现的而不是发明的,换句话说,我们可以将经常合到一起的几种模式用一个新的模式来命名,它是复合模式,但是也可以用别的模式来命名。(转载保留 Phodal's
Blog Phodal's zenthink)
设计模式算是简化了我们在面向对象设计时候的诸多不足,这个在系统设计的初期有时候会有一定的作用,不过多数时候对于我来说,会用上他的时候,多半是在重构的时候,因为不是很熟悉。
观察者模式
观察者模式又叫做发布-订阅(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的情况下。
相关文章推荐
- Ubuntu 安装ruby2.0.0 无法安装
- 庞果网在线编程之最长有效括号长度问题ruby解答
- 如何删除RubyGem
- Ruby rails 页面跳转(render和redirect_to)
- openSUSE 安装 Ruby on rails <1>
- Ruby on rails 实战圣经:ActiveRecord
- ruby gem install rails 错误解决
- [RMXP发布] [Ruby] 对象序列化 Marshal 格式 dump 规则
- ruby on rails学习第3篇:创建第一个gem(转载)
- ruby rails 的复制 dup clone
- ruby rails的好博客
- 一个python程序员的ruby三日游(三)——构建工具
- Ruby On Rails-2.0.2源代码分析(1)-Rails的启动
- 庞果网直方图中面积最大问题ruby解答
- ruby File.basename函数
- ruby can not load such file readline
- 庞果网回文数问题ruby解答
- 一个python程序员的ruby三日游(二)——第一天 ruby rspec
- ruby sleep函数及常用的方法
- 每个程序员都应该学习使用Python或Ruby