设计模式(十六)—观察者模式
最后更新于:2022-04-01 16:26:27
**定义**:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
## 一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340bd8b1c.jpg)
Subject被观察者
---|定义被观察者必须实现的职责,它必须能够动态的增加、取消观察者,一般是抽象类或者实现类,完成管理观察者并通知观察者。
Observer观察者
---|观察者接到信息后,进行update操作
ConcreteSubject具体的被观察者
---|定义被观察者自己的业务逻辑,同时定义对那些事件进行通知
ConcreteObserver具体的观察者
---|每个观察者在接收到信息后的处理反应是不同的,各个观察者有自己的处理逻辑。
~~~
public class ObserverTest {
public static void main(String[] args) {
//创建一个呗观察者
ConcreteSubject con = new ConcreteSubject();
//创建一个观察者
Observer observer = new ConcreteObserver();
//添加到被观察者类中
con.addObserver(observer);
//完成某项任务,实现更新
con.doSomething();
}
}
/**
* 观察者接口,所有观察者要实现该接口。
* 实现方法, 处理不同的业务逻辑。
* @author admin
*
*/
interface Observer{
public void update();
}
/**
* 具体的观察者实现类。
* @author admin
*
*/
class ConcreteObserver implements Observer{
@Override
public void update() {
System.out.println("观察者接收到信息,去实现业务逻辑.......");
}
}
/**
* 被观察者抽象类,
* 主要对观察者的操作,增加、删除、通知所有观察者等方法。
* @author admin
*
*/
abstract class Subject{
//定义一个观察者集合
private List<Observer> observerList = new ArrayList<Observer>();
//添加一个观察者
public void addObserver(Observer o){
this.observerList.add(o);
}
//删除一个观察者
public void removeObserver(Observer o){
this.observerList.remove(o);
}
//通知所有的观察者
public void notifyObserver(){
for(Observer o : observerList){
o.update();
}
}
}
/**
* 被观察者的具体实现类,
* 当被观察者完成某种操作以后,
* 观察者会产生相应的更新操作
* @author admin
*/
class ConcreteSubject extends Subject{
public void doSomething(){
System.out.println("被观察者完成操作....");
super.notifyObserver();
}
}
~~~
## 一个例子:
韩国的韩非子是一个十分重要的任务,因此他身边被安插好多各个国家的间谍,来监视他的一举一动。
当韩非子有任何的行动间谍都要做相应的变化。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340bf37b9.jpg)
~~~
public class ObserverT {
public static void main(String[] args) {
//创建一个被观察者
HanFeiZi hfz = new HanFeiZi();
//创建一个李斯观察者
IObserver lisi = new Lisi();
//创建一个序言观察者
IObserver xuyan = new XuYan();
//添加观察者..
hfz.addOberver(lisi);
hfz.addOberver(xuyan);
//韩非子吃饭..
hfz.haveBreakfast();
}
}
/**
* 被观察者的接口类,
* 定义其日常的行为方法。
* @author admin
*
*/
interface IHanFeiZi{
//吃饭
void haveBreakfast();
//娱乐
void haveFun();
}
/**
* 被观察者的接口类,
* 定义其对身边间谍的增加、删除、通知所有间谍的方法
* @author admin
*
*/
interface IObservable{
void addOberver(IObserver o);
void removeObserver(IObserver o);
void notifyObserver(String context);
}
class HanFeiZi implements IHanFeiZi,IObservable{
//定义一个监听者集合
private List<IObserver> observerList = new ArrayList<IObserver>();
@Override
public void addOberver(IObserver o) {
this.observerList.add(o);
}
@Override
public void removeObserver(IObserver o) {
this.observerList.remove(o);
}
@Override
public void notifyObserver(String context) {
for(IObserver o : observerList){
o.update(context);
}
}
@Override
public void haveBreakfast() {
System.out.println("----韩非子开始吃饭了...");
this.notifyObserver("----韩非子在吃饭.....");
}
@Override
public void haveFun() {
System.out.println("----韩非子开始娱乐了...");
this.notifyObserver("----韩非子在娱乐.....");
}
}
/**
* 观察者接口类,
* 实现该类的子类,对被观察者的举动进行相应的业务逻辑更新。
* @author admin
*
*/
interface IObserver{
public void update(String context);
}
/**
* 具体是观察者实现类..
* @author admin
*/
class Lisi implements IObserver{
@Override
public void update(String context) {
System.out.println("李斯接收到消息,向皇帝报告:");
this.reportToBoss(context);
System.out.println("皇帝没有责罚我,我很开心...");
}
private void reportToBoss(String info){
System.out.println("报告老板,"+info);
}
}
class XuYan implements IObserver{
@Override
public void update(String context) {
System.out.println("序言接收到消息,想丈夫汇报:");
this.reportToHasband(context);
System.out.println("序言表现很好..");
}
public void reportToHasband(String info){
System.out.println("报告老公:"+info);
}
}
~~~
## 观察者模式 的扩展
---|java世界中的观察者模式
java.util.Observer接口和java.util.Observable实现类
为我们提供了观察者模式。
被观察者只需要继承Observable类,就可以实现对监听者的添加、删除、通知等方法,
观察者只要实现Observer接口,就可以完成相应的更新操作。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340c2353d.jpg)
~~~
public class ObserverT {
public static void main(String[] args) {
//创建一个被观察者
HanFeiZi hfz = new HanFeiZi();
//创建一个李斯观察者
Observer lisi = new Lisi();
//创建一个序言观察者
Observer xuyan = new XuYan();
//添加观察者..
hfz.addObserver(lisi);
hfz.addObserver(xuyan);
//韩非子吃饭..
hfz.haveBreakfast();
}
}
/**
* 被观察者的接口类,
* 定义其日常的行为方法。
* @author admin
*
*/
interface IHanFeiZi{
//吃饭
void haveBreakfast();
//娱乐
void haveFun();
}
class HanFeiZi extends Observable implements IHanFeiZi {
@Override
public void haveBreakfast() {
System.out.println("----韩非子开始吃饭了...");
/*
* 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,
* 并调用 clearChanged 方法来指示此对象不再改变。
*/
super.setChanged();
super.notifyObservers("韩非子在吃饭...");
}
@Override
public void haveFun() {
System.out.println("----韩非子开始娱乐了...");
/*
* 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,
* 并调用 clearChanged 方法来指示此对象不再改变。
*/
super.setChanged();
super.notifyObservers("韩非子在娱乐...");
}
}
/**
* 具体是观察者实现类..
* @author admin
*/
class Lisi implements Observer{
@Override
public void update(Observable o, Object arg) {
System.out.println("李斯接收到消息,向皇帝报告:");
this.reportToBoss(arg);
System.out.println("皇帝没有责罚我,我很开心...");
}
private void reportToBoss(Object info){
System.out.println("报告老板,"+info);
}
}
/**
* 具体是观察者实现类..
* @author admin
*/
class XuYan implements Observer{
@Override
public void update(Observable o, Object arg) {
System.out.println("序言接收到消息,想丈夫汇报:");
this.reportToHasband(arg);
System.out.println("序言表现很好..");
}
public void reportToHasband(Object info){
System.out.println("报告老公:"+info);
}
}
~~~
观察者模式的优点
---|观察者和被观察者之间是抽象耦合
---|建立一套触发机制
观察者模式的缺点:
---|观察者模式的效率问题
观察者的使用场景
---|关联行为场景,需要注意的是,关联行为是可拆分的,而不是”组合“关系
---|事件多级触发场景
---|跨系统的消息交换场景,如消息队列的处理机制