ruby、javascript、php中的观察者模式实现代码_ruby专题

面试被问及到js中的观察者模式,这玩意儿早就了解过,可以说是动态语言中非常有用的一个设计模式,非常惭愧的没有系统的研究过。不过没关系,哪里不会补哪里,立刻动手,用所会的语言都实现一遍。

观察者模式

关于观察者模式,《松本行弘的程序世界》讲的非常清楚:观察者模式是当某个对象状态发生变化时,依存于该状态的全部对象自动得到通知,被观察者和观察者们是一对多的关系。书中还举了一个非常易懂的例子:获取系统当前时间并输出到命令行中。如果要硬编码也很简单,定义一个方法,先获取时间,然后再处理展示。这样获取时间的功能基本就不能复用了,因为带了个处理展示的拖油瓶。

如果用观察者模式则可以这样:定义两个类,一个用于计时,获取当前时间;另一个用于展示时间。展示时间的类就是观察者,这样做的好处是降低相互的依赖性。第一个类改变后不需要处理任何事物,只需要发出通知告诉它的观察者们,具体事物由它们处理。比如有一天我们想换种形式展示时间,或者用多种方式展示时间,完全不需要牵扯到第一个类。

PS:《松本行弘的程序世界》真是一本好书。起初是想把这本书当做ruby教程来读的,后来发现根本不是,书中用非常易懂的语言深入浅出的讲明白了很多深奥的哲学思想。虽然这本书对我这种刚入门的菜鸟来说几乎没有什么实用价值,但是读完之后有种豁然开朗的感觉,是一次非常好的阅读体验。

ruby实现

用ruby实现观察者模式简直简单清晰的令人发指,上代码:

复制代码 代码如下:

require "observer"
#被观察者
class Subject
    include Observable
    def notify
        #do sth
        changed #更新标志为真
        notify_observers(*args) #如果更新标志为真,调用观察者带参数args的方法
    end
end
#观察者
class Obs
    #回调函数,好像只能这么叫
    def update
        #do sth
    end
end
#实例
sub = Subject.new
sub.add_observer(Obs.new)
sub.notify

没错,就是这么简单。。。
主要是依靠Observer模块,除了上面用到的,此模块还有如下接口:

1.delete_observer(obj) 删除特定的观察者
2.delete_observers 删除全部观察者
3.count_observers 获取观察者数目
4.changed? 检查更新标志

php实现

php实现起来也不麻烦:

复制代码 代码如下:

//被观察者
class Subject
{
    private $_observers;
    public function __construct() {
        $this->_observers = array();
    }
    public function add_observer($obs) {
        $this->_observers[] = $obs;
    }
    public funtion delete_observer($bos) {
        $index = array_search($bos, $this->_observers);
        unset($this->_observers[$index]);
    }
    public function notify_observers() {
        foreach($this->_observers as $v) {
            $v->update();
        }
    }
}
//观察者
class Observer
{
    public function __construct() {
        do sth;
    }
    public function update() {
        do sth;
    }
}
//实例
$sub = new Subject();
$obs = new Observer();
$sub->add_observer($obs);
$sub->notify_observers();

js实现

js实现起来也不麻烦,就是得写些工具函数方便用,比如删除数组指定的元素。下面只用最简单的实现方法。

复制代码 代码如下:

//被观察者
function Subject() {
    var _this = this;
    this.observers = [];
    this.addObserver = function(obj) {
        _this.observers.push(obj);
    }
    this.deleteObserver = function(obj) {
        var length = _this.observers.length;
        for(var i = 0; i < length; i++) {
            if(_this.observers[i] === obj) {
                _this.observers.splice(i, 1);
            }
        }
    }
    this.notifyObservers = function() {
        var length = _this.observers.length;
        console.log(length)
        for(var i = 0; i < length; i++) {
            _this.observers[i].update();
        }
    }
}
//观察者
function Observer() {
    this.update = function() {
        alert(1)
    }
}
var sub = new Subject();
var obs = new Observer();
sub.addObserver(obs);
sub.notifyObservers();
var sub = new Subject();

结论:ruby可以让我们专注于程序设计本身,而不是程序的语法和特性。js灵活多变,是一门完备的编程语言除了生孩子什么都能实现,就是玩起来要下点功夫。php嘛,中规中矩,没啥好说的。

这仨程序都跑起来后算是彻底明白这个设计模式了。

时间: 2024-09-29 02:33:22

ruby、javascript、php中的观察者模式实现代码_ruby专题的相关文章

实例解析Ruby设计模式开发中对观察者模式的实现_ruby专题

一般来说,观察者模式的定义应该是这样的:building a clean interface between the source of news that some object has changed and the consumers of that news. 观察者模式在消息的生产者和消费者之间建立了clean interface,这样就使得消息的生产者和消费者之间的耦合是抽象的.被观察者可以不认识任何一个的观察者,它只知道他们都实现了一个共同的接口.由于观察者和被观察者没有紧密的耦合

在Ruby on Rails中优化ActiveRecord的方法_ruby专题

 Ruby on Rails 编程常常会将您宠坏.这一不断发展的框架会让您从其他框架的沉闷乏味中解脱出来.您可以用习以为常的几行代码片断表达自己的意图.而且还可以使用 ActiveRecord. 对于我这样的一个老 Java? 程序员而言,ActiveRecord 多少有点生疏.通过 Java 框架,我通常都会在独立的模型和模式之间构建一种映射.像这样的框架就是映射框架.通过 ActiveRecord,我只定义数据库模式:或者用 SQL 或者用称为迁移(migration)的 Ruby 类.将对

详解Ruby设计模式编程中对单例模式的运用_ruby专题

简介      单例模式是设计模式中最简单的形式之一.这一模式的目的是使得类的一个对象成为系统中的唯一实例.要实现这一点,可以从客户端对其进行实例化开始.因此需要用一种只允许生成对象类的唯一实例的机制,"阻止"所有想要生成对象的访问.使用工厂方法来限制实例化过程.这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义. 要点      显然单例模式的要点有三个:一是某个类只能有一个实例:二是它必须自行创建这个实例:三是它必须自行向整个系统提供这个实例.      

在Ruby on Rails中使用Markdown的方法_ruby专题

实现 Markdown 语法和代码语法高亮分别是用的 Redcarpet 和 pygments.rb 两个 Gem:     https://github.com/vmg/redcarpet     https://github.com/tmm1/pygments.rb     https://github.com/richleland/pygments-css     http://pygments.org/docs/lexers/ 在/Gemfile中添加如下两行: gem 'redcarp

举例讲解Ruby中require的使用方法_ruby专题

同一目录下的文件,如/usr/local/ruby/foo.rb与/usr/local/ruby/bar.rb两个文件. 如果直接在foo.rb中   require 'bar' 执行时会报找不到bar.rb错误. 这是因为运行   /home/oldsong$ ruby /usr/local/ruby/foo.rb 时会在ruby安装的lib目录和/home/oldsong/目录下查找bar.rb.而不会去rb文件的目录/usr/local/ruby/下查找. 所以除引用系统rb外,requi

提升Ruby on Rails性能的几个解决方案_ruby专题

简介 Ruby On Rails 框架自它提出之日起就受到广泛关注,在"不要重复自己","约定优于配置"等思想的指导下,Rails 带给 Web 开发者的是极高的开发效率. ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate 即可实现非常易用的持久化,Github 和 Rubygems 上丰富多样的 Rails 插件是 Rails 开发高效率的又一有力保障.Rails 是一个真正彻底的 MVC(Model-View-Controller) 框

简单的Ruby中的Socket编程教程_ruby专题

Ruby提供了两个级别访问网络的服务,在底层你可以访问操作系统,它可以让你实现客户端和服务器为面向连接和无连接协议的基本套接字支持. Ruby 统一支持应用程的网络协议,如FTP.HTTP等. 不管是高层的还是底层的.ruby提供了一些基本类,让你可以使用TCP,UDP,SOCKS等很多协议交互,而不必拘泥在网络层.这些类也提供了辅助类,让你可以轻松的对服务器进行读写. 接下来就让我们来学习如何进行 Ruby Socket 编程什么是 Sockets 应用层通过传输层进行数据通信时,TCP和UD

Ruby进行文件信息输出实例代码_ruby专题

演示代码: [code]#!/usr/bin/env ruby COUNT = 10 require 'benchmark' $account_chars = ('A'..'Z').to_a.delete_if {|c| c =~ /[AEIOUY]/ } #$password_chars = ('0'..'9').to_a $password_chars = Array.new $password_chars[0..9] = ('0'..'9').to_a $password_chars[10

Ruby编程中的命名风格指南_ruby专题

用英语命名标识符.    # bad - identifier using non-ascii characters заплата = 1_000 # bad - identifier is a Bulgarian word, written with Latin letters (instead of Cyrillic) zaplata = 1_000 # good salary = 1_000     使用snake_case的形式给变量和方法命名.     # bad :'some sy