设计模式一之观察者模式
1. 概念
观察者模式(有时又被称为发布/订阅模式)是软体设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。
上边是比较官方的说发,个人理解这种模式就是一对多的监听回调,比如老板发布QQ消息通知所有自己的员工某天放假,首先老板手下的员工是不停变换的,有离职的有新加入的,所以老板的员工是一对多的关系,而员工是不停变化的,所有员工通过加入老板QQ群或离开QQ群和老板建立关系或解除关系,老板群里发布消息后所有注册为自己的员工收到消息明天放假,不上班,每一个员工根据消息安排自己明天的事物。这就是一对多的关系。老板和员工通过QQ群建立一对多的关系(QQ群只是例子,默认只有老板能发布消息,员工不能发布消息,互不干涉)。
2.代码实现
以下是简单的代码实现,已员工和老板为例,主要看注解。
/**
* 观察者模式中“一”(被观察者)的基础接口
* Created by 1 on 2016/4/23.
*/
public interface Observable {
/**
* 注册观察者
* @param observe
*/
void registerObserver(Observe observe);
/**
* 移除观察者
* @param observe
*/
void removeObserver(Observe observe);
/**
* 被观察者状态改变
*/
void notifyObserver();
}
/**
* 监察者基础接口,每个监察者必须实现
* Created by 1 on 2016/4/23.
*/
public interface Observe {
/**
* 可以有许多方法,观察者接收到消息后处理
* @param temp
*/
void update(String temp);
}
/**
* 老板类(被观察者,实现被观察者接口)
* Created by 1 on 2016/4/23.
*/
public class BossObservable implements Observable {
//员工(监察者)列表
private ArrayList<Observe> arrayListObserve;
public BossObservable(){
arrayListObserve = new ArrayList();
}
/**
* 入职成为老板员工(加入QQ群)
* @param observe 要注册的监察者
*/
@Override
public void registerObserver(Observe observe) {
arrayListObserve.add(observe);
}
/**
* 员工离职(离开QQ群)
* @param observe
*/
@Override
public void removeObserver(Observe observe) {
arrayListObserve.remove(observe);
}
/**
* 老板给所有员工发送消息(老板在群里发布消息)
*/
@Override
public void notifyObserver() {
for (int j = 0;j < arrayListObserve.size();j++){
arrayListObserve.get(j).update("明天放假");
}
}
}
/**
* 第一个监察者(员工First)
* 若新加监察者只需实现接口
* Created by 1 on 2016/4/23.
*/
public class FirstStaffObserve implements Observe{
/**
* 监测到老板在QQ发布放假消息
* @param temp 放假消息
*/
@Override
public void update(String temp) {
System.out.print("FirstStaff"+temp);
}
}
/**
* 第二个监察者(Second员工)
* 若新加监察者只需实现接口并且注册成为监察者
* Created by admin on 2016/4/23.
*/
public class SecondStaffObserve implements Observe{
/**
* 监测到老板在QQ发布放假消息
* @param temp 放假消息
*/
@Override
public void update(String temp) {
System.out.print("SecondStaff"+temp);
}
}
//测试类
public class Test
{
public static void main(String[] args)
{
BossObservable boss = new BossObservable();
FirstStaffObserve firstStaffObserve = new FirstStaffObserve();
SecondStaffObserve secondStaffObserve = new SecondStaffObserve();
//注册监察者(员工入职)
boss.registerObserver(firstStaffObserve);
boss.registerObserver(secondStaffObserve);
//通知放假
boss.notifyObserver();
boss.removeObserver(firstStaffObserve);
}
}
注:以上例子只为了解监察者模式原理,若是真实使用,方法会传入各种参数,以及多个方法,随自己使用而变化。
3.总结
观察这模式使用场景:
一般button添加点击事件,对于某个事件发生改变做出监听。一对多进行通知等。
观察者模式的效果有以下的优点:
第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。
由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。
第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。
观察者模式有下面的缺点:
第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的,仅仅知道发生了什么变化而已。