一. 观察者模式(警察观察嫌疑犯)
1. 介绍
观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,是一种对象行为型模式。
观察模式有点类似订阅模式,但是与订阅模式不同之处在于订阅模式发布者和接收者没有直接的联系,而观察者和被观察主题是直接耦合在一起的。
观察者模式是一种对象行为型模式,其主要优点如下:
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
- 目标与观察者之间建立了一套触发机制。
它的主要缺点如下:
- 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
- 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
现在我们举一个类似的情况,并使用代码来实现,为大家提供一个比较明显的认识。
2. 例子
警察在找到嫌犯的时候,为了找到幕后主使,一般都会蹲点监察,这里我有三名便衣警察来蹲点监察2名嫌犯,三名便衣分别是:李Sir,陈Sir,王Sir,两名嫌犯是:天哥与地藏哥,详见代码:
观察者 Observer
/**
* 观察者
*/
public interface Observer {
void update(String message,String name);
}
警察 Policeman 实现观察者接口
/**
* 警察观察者
*/
public class Policeman implements Observer {
//定义姓名
private String policeName = "无名警察";
public Policeman(String policeName) {
this.policeName = policeName;
}
//接收通知
@Override
public void update(String message, String name) {
System.out.println(policeName+":"+name+"那里有新情况:"+ message);
}
}
被观察主题 Subject
/**
* 被观察主题
*/
public interface Subject {
//添加观察者
void addObserver(Observer observer);
//移除观察者
void removeObserver(Observer observer);
//通知观察者
void notice(String message);
}
嫌犯 Suspect 实现被观察者接口
/**
* 嫌犯
*/
public class Suspect implements Subject {
private String name = "未命名嫌犯";
//定义观察者集合,既警察
private List<Observer> observerList = new ArrayList<>();
public Suspect(String name) {
this.name = name;
}
//填加观察者
@Override
public void addObserver(Observer observer) {
if(!observerList.contains(observer)){
observerList.add(observer);
}
}
//移除观察者
@Override
public void removeObserver(Observer observer) {
if(observerList.contains(observer)){
observerList.remove(observer);
}
}
//通知观察者
@Override
public void notice(String message) {
if (observerList.size() != 0) {
for(Observer observer:observerList){
observer.update(message,name);
}
}
}
}
主程序 Main
public class Main {
public static void main(String[] args) {
//定义两个嫌犯
Suspect suspect1 = new Suspect("天哥");
Suspect suspect2 = new Suspect("地藏哥");
//定义三个观察便衣警察
Policeman policeman1 = new Policeman("李Sir");
Policeman policeman2 = new Policeman("陈Sir");
Policeman policeman3 = new Policeman("王Sir");
//为嫌犯1增加观察便衣
suspect1.addObserver(policeman1);
suspect1.addObserver(policeman2);
//为嫌犯2增加观察便衣
suspect2.addObserver(policeman2);
suspect2.addObserver(policeman3);
//定义嫌犯1的情况
String message1 = "又砸了一个场子";
suspect1.notice(message1);
//定义嫌犯2的情况
String message2 = "又卖了一批货";
suspect2.notice(message2);
}
}
结果:
3. 总结
通过上面的实例可以很明显的看出,观察者模式的大概模型,关键是什么呢?
-
针对观察者与被观察者分别定义接口,有利于分别进行扩展。
-
重点在于被观察者,被观察者需要实现填加、删除、通知观察者这三个功能。
-
观察者中需要有个接收被观察者通知的方法。
如此而已!
观察者模式定义的是一对多的依赖关系,一个被观察者可以拥有多个观察者,并且通过接口对观察者与被观察者进行逻辑解耦,降低二者的直接耦合。
如此这般,想了一番之后,突然发现这种模式与桥接模式有点类似的感觉。
桥接模式也是拥有双方,同样是使用接口(抽象类)的方式进行解耦,使双方能够无限扩展而互不影响,区别在于:
-
主要就是使用场景不同,桥接模式主要用于实现抽象与实现的解耦,主要目的也正是如此,为了双方的自由扩展而进行解耦,这是一种多对多的场景。观察者模式侧重于另一方面的解耦,侧重于监听方面,侧重于一对多的情况,侧重于一方发生情况,多方能获得这个情况的场景。
-
另一方面就是结构不同,在观察者模式中存在许多独有的内容,如观察者集合的操作,通知的发送与接收,而在桥接模式中只是简单的接口引用。