(有时又被称为模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式)
观察者模式还有一个名字叫发布-订阅模式,我们熟悉的消息队列如ActiveMQ,就是采用的这种设计模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象状态改变,所有的依赖对象都将得到通知。
关键代码:在抽象类里有一个 ArrayList 存放观察者们。
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
(1)Subject:抽象主题,他把所有观察者对象保存在一个集合里,可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。意思就是明星把所有的粉丝都保存在一个账号里面,粉丝数量不限,可以新增粉丝也可以拉黑粉丝。
(2)Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。这就是我们所有粉丝的抽象。
(3)ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。具体每一个粉丝。
步骤 1
/*
主题Subject
*/
import java.util.*;
public class Subject {
//观察者数组
private List observers
= new ArrayList();
//增加一个观察者
public void addObserver(Observer observer)
{
this.observers.add(observer);
}
//删除一个观察者
public void deleteObserver(Observer observer)
{
this.observers.remove(observer);
}
//通知所有观察者
public void notifyAllObservers(String msg){
for (Observer observer : observers) {
observer.update(msg);
}
}
}
步骤 2
/*
观察者Observer
*/
public abstract class Observer {
protected Subject subject;
public abstract void update(String msg);
}
步骤 3
/*
具体观察者
*/
public class ConcreteObserver extends Observer {
private String name;
public ConcreteObserver(String name)
{
this.name=name;
}
@Override
public void update(String msg) {
System.out.println(name+"收到消息"+msg);
}
}
步骤 4
/*
观察者模式(Observer Pattern)
使用 Subject 和实体观察者对象。
*/
public class ObserverPatternDescription {
public static void main(String[] args) {
Subject subject = new Subject();
//定义一个观察者
Observer observer=new ConcreteObserver("小李");
Observer observer2=new ConcreteObserver("小红");
Observer observer3=new ConcreteObserver("小明");
//观察
subject.addObserver(observer);
subject.addObserver(observer2);
subject.addObserver(observer3);
//开始活动
subject.notifyAllObservers("处理中。。。");
}
}
结果
小李收到消息处理中。。。
小红收到消息处理中。。。
小明收到消息处理中。。。