原文链接:http://www.wangqi94.com/to/master/blog?uuid=75
前言
观察者模式是非常常用的设计模式之一。在软件系统中,当一个对象的行为依赖于另外一个对象的状态时,观察者模式就相当有用了。若不适用观察者模式提供的通用结构,而需要实现其类似的功能,则只能在另外一个线程中不停的监听对象所依赖的状态。在一个复杂的系统中,可能会因此开启很多线程来实现这一功能,这将是系统的性能产生额外的负担。观察者模式的意义也就在此,它可以在单线程中,是某一对象,即使得知自身所依赖的状态的变化。
什么是观察者模式
观察者模式的经典结构如下图所示:
ISubject是被观察对象,它可以增加和删除观察者。IObserver是观察者对象,它依赖ISubject的状态变化。当ISubject状态发生变化时,会通过inform()方法通知观察者。
观察者模式的主要角色及作用:
`主题接口`:指被观察的对象。当其状态发生改变或者某事件发生时,它会将这个变化通知观察者,它维护了观察者所需要依赖的状态。
`具体主题`:具体主题实现了主题接口中的方法。如新增观者这、删除观者者和通知观察者。其内部维护了一个观察者列表。
`观察者接口`:观察者接口定义了观察者对象的基本方法。当依赖的状态发生变化时,主题接口就会调用观察者的update方法。
`具体观察者`:实现了观察者接口的update(),具体处理当被观察者状态改变时或者某一事件发生时的业务逻辑。
看下上述观察者结构对应的代码实现:
主题接口的实现:
/**
* @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
* @Date: 2019-4-30 0030 21:07
* @Description: 主题接口 / 被观察者
*/
public interface ISubject {
void attach(IObserver observer); // 添加观察者
void detach(IObserver observer); // 删除观察者
void inform(); // 通知所有的观察者
}
观察者接口的实现:
/**
* @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
* @Date: 2019-4-30 0030 21:09
* @Description: 观察者接口
*/
public interface IObserver {
void update(Object event); // 更新事件
}
一个具体的主题实现,注意,它维护了观察者队列,提供了增加和删除观察者的方法,并通过inform()通知所有观察者。
/**
* @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
* @Date: 2019-4-30 0030 21:10
* @Description: 一个具体的主题实现
*/
public class ConcreteSubject implements ISubject {
Vector<IObserver> observers = new Vector<IObserver>();
@Override
public void attach(IObserver observer) {
observers.addElement(observer);
}
@Override
public void detach(IObserver observer) {
observers.removeElement(observer);
}
@Override
public void inform() {
for (IObserver observer : observers){
// 这里通知所有的观察者
observer.update(null);
}
}
}
两个具体的观察者实现如下,当它监听的状态发生变化时,update()方法就会被主题回调,进而可以在观察者内部进行业务处理:
/**
* @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
* @Date: 2019-4-30 0030 21:13
* @Description: 一个具体的观察者
*/
public class ConcreteObserver1 implements IObserver {
@Override
public void update(Object event) {
System.out.println("observer1 receives information");
}
}
/**
* @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
* @Date: 2019-4-30 0030 21:13
* @Description: 一个具体的观察者
*/
public class ConcreteObserver2 implements IObserver {
@Override
public void update(Object event) {
System.out.println("observer2 receives information");
}
}
来,测试下,看看结果是否符合预期:
/**
* @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
* @Date: 2019-4-30 0030 21:15
* @Description: 观察者模式测试
*/
public class SubjectObserverModelTest {
public static void main(String[] args) {
ISubject subject = new ConcreteSubject();
IObserver observer1 = new ConcreteObserver1();
IObserver observer2 = new ConcreteObserver2();
// add 观察者
subject.attach(observer1);
subject.attach(observer2);
// 通知
subject.inform();
System.out.println("---------------- 分隔符 ---------------");
// remove 观察者
subject.detach(observer2);
// 再次通知
subject.inform();
}
}
执行结果如下:
JDK提供了观察者模式
显然符合我们的预期。观察者模式是很简单,所以也比较常用,以至于JDK内部已经为开发人员准备了一套观察者模式的实现。它位于java.util包中,包括java.util.Observable类和java.util.Observer接口,他们的关系如下图所示:
在java.util.Observable类中,已经实现了主要的功能,如增加观察者、删除观察者和通知观察者,开发人员可以直接通过继承Observable使用这些功能。java.util.Observer接口是观察者接口,它的update()方法会在java.util.Observable的notifyObservers()方法中被回调,以获得最新的状态变化。通常在观察者模式中Observer接口总是应用程序的核心扩展对象,具体的业务逻辑总是会被封装在update()方法中。
总结
(1):观察者模式可以用于事件监听、通知发布等场合。可以确保观察者在不适用轮询监控的情况下,及时收到相关消息和事件。
(2):在JDK中已经实现了一套观察者模式,我们可以直接复用它。
RelaxHeart网 - Tec博客: 我的更多文章