首页 > 代码库 > 面向对象的设计模式(七),观察者模式

面向对象的设计模式(七),观察者模式

似乎全部的设计模式都是为了使得程序具有低耦合,灵活性高,可扩展性好。程序结构清晰等等。

今天的这个设计模式—观察者模式自然也不例外。但程序结构清晰可能就不是重点了。

好吧,废话少说,模式这样的简单粗暴的东西还是要快点学习。以下直接进入正题。

定义:观察者模式是让对象与对象之前建立一种一对多(不是Bean之前的一对多)的关系,这样的关系使得当一的一方的状态改变时,全部多的一方自己主动依据一的一方的改变做出对应的改变。

使用场景:

  1. 事件多级触发。如一个公司,CEO是最顶层的被观察者(一的一方),观察CEO的有多个经理,如:多个总经理(多的一方)同一时候观察CEO。而每一个总经理有能够被多个其它经理观察,如:项目经理,产品经理等,那么这里的总经理即是观察者也是二级被观察者,那么仅仅要CEO发话,相关的总经理就要做出改变,而总经理可能又要让底下的项目经理和业务经理做出改变,这就是事件多级触发;

  2. 关联绑定行为,关联行为能够拆分,即解除绑定,不是“组合”,即两个行为是相互独立的,不是一个总体;

  3. 跨系统消息交换场景。如消息队列,事件总线处理机制。

长处:

  1. 增强程序的灵活性,可扩展性;

  2. 减少程序耦合性。

缺点:

  • 因为这样的模式实际上是通过被观察者用一个集合存放全部的观察者的引用。然后依次遍历集合调用每一个观察者的update方法。所以,这就产生了开发效率和执行效率的问题。还有,通常遍历是顺序的,那么全部的观察者实际上不是同一时候做出更新的。更有甚者,假设当中一个观察者更新出现卡顿。那么后面的观察者就要延迟做出更新了,在这样的情况下,通常採用多线程异步方式。然而。带来了新的问题-并发。

以下先通过JDK自带的Observer类和Observable实现观察者模式

代码实现(利用JDK内置对象)

被观察者:

import java.util.Observable;
/**
 * 被观察者
 * @author lt
 *
 */
public class BeObservered extends Observable{

    /**
     * 提交改变,调用Observable的setChanged()和notifyObservers();
     * 注意:必须调用setChanged()。然后notifyObservers()才有效
     */
    public void postChanged(Object news){
        // 标识被被观察者有新的改变
        setChanged();
        // 通知全部的观察者
        notifyObservers(news);
    }
}

?注意:

  • postChanged()是我们自己写的方法;
  • 必须在这种方法里面同一时候调用setChanged()notifyObservers()观察者才会接受到变化。即回调update方法。

观察者:

import java.util.Observable;
import java.util.Observer;

/**
 * 观察者
 * @author lt
 *
 */
public class MyObserver implements Observer{

    private String name;

    public MyObserver(String name){
        this.name = name;
    }

    /**
     * @param observable 该观察者观察的被观察者 即BeObservered
     * @param BeObservered调用notifyObservers(Object arg)时传入的arg參数
     */
    @Override
    public void update(Observable observable, Object news) {
        System.out.println(name+"接受到变化"+",更新的内容为:"+news);
    }

    @Override
    public String toString() {
        return "MyObserverName=" + name + "]";
    }
}

?这里在update方法里面做了点简单的反馈。

測试:

public class Test {

    public static void main(String[] args) {
        MyObserver observer1 = new MyObserver("小明");
        MyObserver observer2 = new MyObserver("小丽");
        MyObserver observer3 = new MyObserver("小强");

        BeObservered beObervered = new BeObservered();
        // 加入到观察者队列
        beObervered.addObserver(observer1);
        beObervered.addObserver(observer2);
        beObervered.addObserver(observer3);

        // 提交改变
        beObervered.postChanged("2016。新年快乐。");
    }
}

?今天是新年2016的第一天。祝福大家新年快乐,心想事成。万事如意。

结果:

技术分享

结果不用说,大家都给点反馈了(哈哈,文章点个赞,评论一番也是挺爽的)。

上面使用了JDK内置对象来实现观察者模式,事实上我们也能够自己来实现观察者模式。以下我们自己来实现观察者模式吧。

自己定义实现观察者模式:

被观察者:

import java.util.HashSet;
import java.util.Set;


/**
 *自己定义被观察者
 * @author lt
 *
 */
public class Observable {

    public Set<Observer> observers = new HashSet<Observer>();
    public boolean isChanged; // 默觉得false

    public void addObserver(Observer o){
        // 防止多线程
        synchronized (observers) {
            observers.add(o);
        }
    }

    public void setChanged(){
        this.isChanged = true;
    }

    public void notifyObservers(Object arg){
        if(isChanged){
            // 遍历集合。依次通知全部的观察者
            for(Observer observer : observers){
                observer.update(this, arg);
            }
            isChanged = false; // 重置
        }
    }

    public void notifyObservers(){
        notifyObservers(null);
    }
}

观察者:

public interface Observer {

    public void update(Observable observable, Object news);
}

OK,自己定义实现观察者模式完毕了,将上面的MyObserverBeObservered导入的JDK的Observer及Observable改成我们自己写的,执行Test測试。

结果:

?和用JDK的Observer及Observable是一样的,再次祝大家新年快乐。心想事成。万事如意。。

OK。到这里我们自己定义实现观察者模式就完毕了,是不是感觉好简单,就是一个回调。

事实上。这里也并不简单,里面肯定涉及到好多东西。什么优化啊,安全啊什么的。

我们上面自己写的类就做了一个同步处理。其它的都没做。大家也能够去看看JDK源代码。看看它是怎么做的。

总结:

?观察者模式基本的作用是用于对象解耦。基于抽象接口(易扩展)ObserverObservable,将观察者和被观察者全然分离(低耦合),实现当被观察者发生改变时对应的全部的观察者选择做出改变。

这点有非常多的用途。如我们Android开发一个软件下载市场等须要不同的Activity能够同一时候须要看到同一个软件下载的进度。还有ListView中也用到了这样的模式等等。同一时候,知道了这样的模式的原理后,我们自己也能够定义我们的观察者和被观察者。

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

面向对象的设计模式(七),观察者模式