观察者模式(Observer Pattern)
观察者模式(Observer Pattern)也叫发布订阅模式(Publish/subscribe),它是一个在项目中经常 的模式,其定义如下:
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. (定义对象间一种“一对多”的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新)
观察者的通用类图
- Subject 被观察者
定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。 - Observer观察者
观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。 - ConcreteSubject具体的被观察者
定义被观察者自己的业务,同时定义对哪些事件行通知。 - ConcreteObserver具体的观察者
每个观察者在接收到消息后的处理反应是不同的,各个观察者有自己的处理逻辑。
观察者模式的优点
1. 观察者和被观察者之间是抽象耦合
如何设计,则不 管是增加观察者还是被观察者都非常容易,而且在Java中都已经被盖同的层级的定义,在系统方面更是得心应手。
2. 建立一套触发机制
根据单一职责原则,每个类的职责是单一的,那么怎么把这个单一的串联成真实世界的复杂逻辑关系呢?比如我们去打猎,打死了一只母鹿,母鹿有三个幼崽,因后援会以了母鹿而饿死,继而……然后……这就是一个触发机制,形成了一个触发链。观察者模式可以完美实现这里的链条形式。
观察者模式的缺点
观察者模式需要考虑一下开发效率和运行效率量,一个空间站以者,多个观察者,开发和高度就会比较复杂,而且Java中消息的通知默认是顺序执行,一个观察者卡壳,会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。
多级触发时的效率更是让人担忧,大家在设计时注意考虑。
观察者模式的使用场景
1. 关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系。
2. 事件多级触发场景。
3. 跨系统的消息交换场景,如消息队列的处理机制。
Subject类
package patterns.Observer.useUtil;
import java.util.Observable;
public class 信息暴露狂 extends Observable {
private int 道德 = 50;
private int 智商 = 50;
private int 体重 = 50;
public 信息暴露狂() {
System.out.println("我是暴露狂,我做什么事都要让别人知道!!!");
}
@Override
public String toString() {
return "目前此人 道德"+道德+" 智商"+智商+" 体重"+体重;
}
public void 吃() {
System.out.println("我吃");
体重++;
setChanged(); //此处不调不触发下一句事件!!!!特别注意!!!
this.notifyObservers("各种美拍高大上");
}
public void 喝() {
System.out.println("我喝");
体重++;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 拉() {
System.out.println("我拉");
体重--;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 撒() {
System.out.println("我撒");
体重--;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 睡() {
System.out.println("我睡");
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 坑() {
System.out.println("我坑");
道德--;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 蒙() {
System.out.println("我蒙");
智商--;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 拐() {
System.out.println("我拐");
体重--;
道德--;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 骗() {
System.out.println("我骗");
智商++;
道德--;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 偷() {
System.out.println("我偷");
体重--;
道德--;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public void 学习() {
System.out.println("我学习");
智商++;
道德++;
setChanged();
this.notifyObservers("各种美拍高大上");
}
public int get道德() {
return 道德;
}
public int get智商() {
return 智商;
}
public int get体重() {
return 体重;
}
}
Main
package patterns.Observer.useUtil;
import java.util.Observable;
import java.util.Observer;
public class Client {
//观察者模式执行场景
public static void main(String[] args) {
Observer 朋友圈 = new Observer() {
@Override
public void update(Observable o, Object arg) {
//处理传来的值
if(o instanceof 信息暴露狂){
信息暴露狂 human = (信息暴露狂)o;
//“拉”信息
int 道德 = 10*human.get道德();
int 智商 = 10*human.get智商();
int 体重 = 10*human.get体重();
String after = arg+"加道德"+道德+"、加智商"+智商+"、加体重"+体重+"=====";
System.out.println("发到【朋友圈】:"+after+" - "+o);
}
}
};
Observer 微博 = new Observer() {
@Override
public void update(Observable o, Object arg) {
//“推”信息
System.out.println("发到【微博】:"+arg+" - "+o);
}
};
信息暴露狂 老陈头 = new 信息暴露狂();
老陈头.addObserver(朋友圈);
老陈头.吃();
老陈头.喝();
老陈头.addObserver(微博); //拉巴巴的时候注册了微博
老陈头.拉();
老陈头.撒();
老陈头.睡();
老陈头.坑();
老陈头.deleteObserver(朋友圈); //不再玩朋友圈了
老陈头.蒙();
老陈头.拐();
老陈头.骗();
老陈头.偷();
老陈头.学习();
}
}
运行结果
我是暴露狂,我做什么事都要让别人知道!!!
我吃
发到【朋友圈】:各种美拍高大上加道德500、加智商500、加体重510===== - 目前此人 道德50 智商50 体重51
我喝
发到【朋友圈】:各种美拍高大上加道德500、加智商500、加体重520===== - 目前此人 道德50 智商50 体重52
我拉
发到【微博】:各种美拍高大上 - 目前此人 道德50 智商50 体重51
发到【朋友圈】:各种美拍高大上加道德500、加智商500、加体重510===== - 目前此人 道德50 智商50 体重51
我撒
发到【微博】:各种美拍高大上 - 目前此人 道德50 智商50 体重50
发到【朋友圈】:各种美拍高大上加道德500、加智商500、加体重500===== - 目前此人 道德50 智商50 体重50
我睡
发到【微博】:各种美拍高大上 - 目前此人 道德50 智商50 体重50
发到【朋友圈】:各种美拍高大上加道德500、加智商500、加体重500===== - 目前此人 道德50 智商50 体重50
我坑
发到【微博】:各种美拍高大上 - 目前此人 道德49 智商50 体重50
发到【朋友圈】:各种美拍高大上加道德490、加智商500、加体重500===== - 目前此人 道德49 智商50 体重50
我蒙
发到【微博】:各种美拍高大上 - 目前此人 道德49 智商49 体重50
我拐
发到【微博】:各种美拍高大上 - 目前此人 道德48 智商49 体重49
我骗
发到【微博】:各种美拍高大上 - 目前此人 道德47 智商50 体重49
我偷
发到【微博】:各种美拍高大上 - 目前此人 道德46 智商50 体重48
我学习
发到【微博】:各种美拍高大上 - 目前此人 道德47 智商51 体重48