设计模式 观察者模式 — ruby/tk小时钟

? ? ?以前看用java实现设计模式,很是头疼,那么多的java概念融合在里面,完全影响了对模式自身的理解。实现起来也是相当麻烦。但是在ruby中,模式理解起来是那么的容易,倒是觉得使用ruby来理解设计模式挺靠谱的。

? ? ?先介绍一种模式-观者者模式。

??百度百科名片 写道

观察者<Observer>模式(有时又被称为发布-订阅<Publish/Subscribe>模式、模型-视图<Model/View>模式、源-收听者<Source/Listener>模式或从属者<Dependents>模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。

?

? ? ? 通俗点说就是A对象(被观察)通知另一个(一些)对象(观察者)自己发生改变了,改变了什么,至于你们这些对象要做什么就不关我的事了,你们自己做去吧!耦合度就此降低了。。。

?一段简单的Ruby 观察者模式的实现:

?

?

?

#!/usr/bin/env rubyrequire 'observer'class CheckWaterTemperature  include Observable  def run    loop do      changed()      notify_observers(Time.now)      sleep 1    end  endendclass ClockView  def update (time)    puts time  endendchecker = CheckWaterTemperature.newchecker.add_observer(ClockView.new)checker.run

?这段中代码包含两个类,顾名思义ClockView是用来展示的,而Clock就是被观察的对象了。当被观察的对象有改变的时候,应该通知观察者们它已经改变了。

在Ruby中通过mix-in方式(类似于java的接口)实现被观察的对象,它的接口有这些:

?

?

#add_observer //增加观察者#changed        //改变当前的状态#changed?      // 查询放钱的状态#count_observers //计数#delete_observer   //删除一个#delete_observers //删除一些#notify_observers //通知观察者们,我已经改变了 

?而观察者只要实现一个方法update,这样通知发生的时候,观察者要做什么就由update实现来决定了。。很容易理解啊。。

上面的示例是通过控制台实现的,增加一个GUI实现,TK实现的,文档可真不好找啊..?

?

?

#!/usr/bin/env ruby# -*- coding: utf-8 -*-require 'observer'require 'thread'require 'tk'=begin     ruby/tk简单的时钟=endclass Clock  #观察者模式  include Observable  def getPointAngle(time)    #获取以y轴为线顺时针的角度,例如:3点钟则时针的角度为90度    sec_angle = time.sec / 60.0 * 360     min_angle = time.min / 60.0 * 360 + sec_angle / 360 / 60    hour_angle = time.hour.divmod(12)[1] / 12.0 * 360 + min_angle / 360 * 12    #转换成以xy轴的角度,例如3点钟,则时针的角度为0度,12点时针的角度为180度    return [hour_angle, min_angle, sec_angle].collect do |x|      x <= 90 ? 90 -x : 450 - x    end  end  def run()    #一秒种刷新一次界面    loop do      angles = self.getPointAngle(Time.now)      changed()            notify_observers(angles)      sleep 1    end  endendclass ClockView  LENGTH_ARRAY = [40, 50, 70]  def initialize(root)    @cur_sec_line = nil    @cur_hour_line = nil    @cur_min_line = nil    @canvas = TkCanvas.new(root)    @canvas.pack('side' => 'left', 'fill' => 'both')    teitem = TkcText.new(@canvas, "text" => "12", "coords" => [95,10])     teitem = TkcText.new(@canvas, "text" => "3", "coords" => [195,95])     teitem = TkcText.new(@canvas, "text" => "6", "coords" => [95,195])     teitem = TkcText.new(@canvas, "text" => "9", "coords" => [5,95])   end  def update(angles)        coords = Array.new    #将角度转换成在界面上的坐标    angles.to_a().each_with_index do |mangle, index|      cy = Math.sin(mangle / 180 * Math::PI) * LENGTH_ARRAY[index]      cx = Math.cos(mangle / 180  * Math::PI) * LENGTH_ARRAY[index]      cx = cx + 100      cy = 100 - cy      coords[index] = [cx, cy]    end    @cur_sec_line != nil and @cur_sec_line.delete()    @cur_min_line != nil and @cur_min_line.delete()    @cur_hour_line != nil and @cur_hour_line.delete()    hline = TkcLine.new(@canvas, 100, 100, coords[0][0], coords[0][1], "width" => "3")    mline = TkcLine.new(@canvas, 100, 100, coords[1][0], coords[1][1], "width" => "2")    sline = TkcLine.new(@canvas, 100, 100, coords[2][0], coords[2][1], "width" => "1")    [hline, mline, sline].map { |aline|       aline.fill 'black'     }    @cur_sec_line = sline    @cur_hour_line = hline    @cur_min_line = mline  endendroot = TkRoot.new do  title '怀旧时钟'     geometry "200x200+1000+80"endclock = Clock.new()clock_view = ClockView.new(root)clock.add_observer(clock_view)Thread.new {  clock.run}Tk.mainloop 

你看报表时,梅里雪山的金丝猴刚好爬上树尖。

设计模式 观察者模式 — ruby/tk小时钟

相关文章:

你感兴趣的文章:

标签云: