一,定义
观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同事监听某一个主题对象,这个主题在状态发生该变时,会通知所有观察者对象,使他们能够自动更新自己。
二,结构
Subject类,可翻译为主题或抽象通知者,一般用一个抽象类或者一个接口实现,他把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者,抽象提供一个接口,可以增加和删除观察者对象。
Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口,抽象观察者一般用一个抽象类或者接口实现,更新接口中通常包含一个Update()方法。
ConcreteSubject类,叫做具体主题或者具体通知者,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给左右登记过得观察者发出通知。
ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口。以便使本身的状态与主题的状态相协调具体观察者角色可以保存一个指向具体主题对象的引用,具体贯彻这叫色通常用一个具体子类实现。
三,示例
//抽象主题(可观察者)
public abstract class Subject {
//创建一个员工观察老板回来的例子
private List<Observer> observerList = new ArrayList<Observer>();
protected String subjectStatus;
public void attach(Observer observer){
observerList.add(observer);
}
public void dttach(Observer observer){
observerList.remove(observer);
}
public void notifyObserver(){
for (Observer observer : observerList){
observer.update();
}
}
}
public class Secretary extends Subject{//具体主题 前台小姐姐
public void setAction(String action){
subjectStatus = action;
}
}
//抽象观察者
public abstract class Observer {
protected String name;
protected Subject sub;
public Observer(String name,Subject sub){
this.name = name;
this.sub = sub;
}
public abstract void update();
}
public class StockObserver extends Observer{//看股票的观察者
public StockObserver(String name,Subject subject){
super(name,subject);
}
@Override
public void update() {
System.out.println(sub.subjectStatus + name + "关闭股票行情,继续工作");
}
}
public class NbaObserver extends Observer{//看NBA的观察者
public NbaObserver(String name, Subject subject){
super(name,subject);
}
@Override
public void update() {
System.out.println(sub.subjectStatus + name + "关闭NBA直播,继续工作");
}
}
//test main
//观察者模式
public static void observerModel(){
Secretary secretary = new Secretary();
NbaObserver nbaObserver = new NbaObserver("老魏",secretary);
StockObserver stockObserver = new StockObserver("小菜",secretary);
secretary.attach(nbaObserver);
secretary.attach(stockObserver);
secretary.setAction("老板回来了!!");
secretary.notifyObserver();
//java自带观察者
DataManager manager = new DataManager();
ObserverA a = new ObserverA(manager);
ObserverB b = new ObserverB(manager);
manager.setDataChange();
}
运行结果:
老板回来了!!老魏关闭NBA直播,继续工作
老板回来了!!小菜关闭股票行情,继续工作
ObserverB 观察到数据变化,然后也要更新啦
ObserverA 观察到数据变化,然后也要更新啦
四,总结
优点:
观察者模式所做的工作其实就是解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使各自的变化都不会影响另一边的变化。
缺点:
观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。但同时,这也算是观察者模式一个缺点,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死。
五,事件委托说明
首先我们看一下观察者模式我们会发现,“抽象通知者”还是依赖“抽象观察者”也就是说,万一没有了抽象观察者这样的接口,我这通知就不能完成了,另外就是每个具体观察者,它不一定是“更新Update()”的方法要调用啊。比如前面的例子,我希望的是关闭NBA直播,关闭股票工具。这个时候我们就用到了委托。
委托:
委托就是一种引用方法的类型。一旦为委托分配了方法,委托将于该方法具有完全相同的行为。委托方法的使用可以像其他任何一个方法一样,具有参数和返回值,委托可以看作是对函数的抽象,是函数的”类”,委托的实例将代表一个具体的函数。
一个委托可以搭载多个方法,所有方法被依次唤起,更重要的是,它可以使委托对象搭载的方法并不需要属于同一个类。
但是委托也有前提,那就是委托对象所搭载的所有方法必须具有相同的原形和形式,也就是拥有相同的参数列表和返回值类型。
参考:《大话设计模式》