1.观察者模式
也叫做发布订阅模式(Publish/subscribe),它是一个在项目中经常使用的模式定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
类图:
四个角色:
Subject被观察者:
定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。
Observer观察者:
观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。
ConcreteSubject具体的被观察者:
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知
ConcreteObserver具体的观察者:
每个观察在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑
2.举个例子
创建一个被观察者Subject,它包含的职责有动态的添加删除观察者,并且向所有的观察者广播消息
package com.wx.observerpattern.base;
import java.util.Vector;
/*
定义一个被观察者,它包含的职责有动态的添加删除观察者,并且向所有的观察者广播消息
*/
public abstract class Subject {
//定义一个观察者数组
private Vector<Observer> observers=new Vector<Observer>();
//增加一个观察者
public void addObserver(Observer observer)
{
this.observers.add(observer);
}
//删除一个观察者
public void delteObserver(Observer observer)
{
this.observers.remove(observer);
}
//当被观察者发生变化的时候 广播到所有的观察者
public void notifyObservers()
{
for (Observer observer:observers)
{
observer.update();
}
}
}
创建一个观察者对象的接口Observer
package com.wx.observerpattern.base;
/*
创建一个观察者对象的接口
*/
public interface Observer {
void update();
}
创建被观察者的具体类ConcreteSubject:
package com.wx.observerpattern.imp;
import com.wx.observerpattern.base.Subject;
public class ConcreteSubject extends Subject {
/*
被观察者的实现类
*/
//这里主要是实现被观察者的方法
public void doSomething()
{
System.out.println("被观察者正在做事!");
}
}
创建观察者的具体类:
package com.wx.observerpattern.imp;
import com.wx.observerpattern.base.Observer;
public class ConcreteObservers implements Observer {
@Override
public void update() {
System.out.println("对被观察者的变化做出反应");
}
}
测试:
package com.wx.observerpattern.test;
import com.wx.observerpattern.imp.ConcreteObservers;
import com.wx.observerpattern.imp.ConcreteSubject;
public class TestObserver {
public static void main(String[] args)
{
//创建一个被观察者
ConcreteSubject subject = new ConcreteSubject();
//创建一个观察者,
ConcreteObservers observers = new ConcreteObservers();
//被观察者被观察
subject.addObserver(observers);
//被观察者广播给所有的观察者
subject.doSomething();
subject.notifyObservers();
}
}
观察者模式的优点:
观察者和被观察者之间是抽象耦合而且在Java中都已经实现的抽象层级的定义,在系统扩展方面更是得心应手。
建立一套触发机制
观察者模式的缺点:
观察者模式需要考虑一下开发效率和运行效率问题,一个被观察者,多个观察者,开发和调试就会比较复杂,而且在Java中消息的通知默认是顺序执行,一个观察者卡壳,会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。多级触发时的效率更是让人担忧,大家在设计时注意考虑
观察者模式的使用场景:
关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系
事件多级触发场景。
跨系统的消息交换场景,如消息队列的处理机制
观察者模式的注意事项:
- 广播链的问题,在一个观察者模式中最多出现一个对象既是观察者也是被观察者,也就是说消息最多转发一次(传递两次),这还是比较好控制的。
2.异步处理问题:被观察者发生动作了,观察者要做出回应,如果观察者比较多,而且处理时间比较长怎么办?那就用异步呗,异步处理就要考虑线程安全和队列的问题