一、观察者模式
观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。UML结构图如下:
其中,Subject类是主题,它把所有对观察者对象的引用文件存在了一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供了一个接口,可以增加和删除观察者对象;Observer类是抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己;ConcreteSubject类是具体主题,将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知;ConcreteObserver是具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协同。
二、没有使用设计模式的代码(模拟炒菜)
package com.wx.wxjob.designPatterns.guanchazhe;
/**
* FileName: NoDesignPatterns
* Author: pengyd
* Date: 2020/7/6
* function: 没有使用观察者模式的代码
*/
public class NoDesignPatterns {
// 倒油
String daoYou;
// 加盐
String jiaYan;
// 料酒
String liaoJiu;
// 模拟炒菜场景
public void stirFry(){
System.out.println("开始炒菜");
System.out.println(daoYou);
System.out.println(jiaYan);
System.out.println(liaoJiu);
}
}
上面的代码有些不足的地方:
1.所有的东西都维护在主类中,而倒油、加盐、料酒等操作并不属于主类的属性,强行放在主类中不合适。
2.如果新增一个加鸡精的操作,需要修改主类,不易维护。
三、利用观察者模式来优化
package com.wx.wxjob.designPatterns.guanchazhe;
/**
* FileName: Observer
* Author: pengyd
* Date: 2020/7/6
* function: 观察者
*/
public interface Observer {
public void chaoCai();
}
package com.wx.wxjob.designPatterns.guanchazhe;
import java.util.Vector;
/**
* FileName: Subject
* Author: pengyd
* Date: 2020/7/6
* function: 被观察者
*/
abstract public class Subject {
private Vector<Observer> observerList = new Vector<>();
public void attachObserver(Observer observer) {
observerList.add(observer);
}
public void detachObserver(Observer observer){
observerList.remove(observer);
}
public void notifyObservers(){
for (Observer observer: observerList){
observer.chaoCai();
}
}
}
package com.wx.wxjob.designPatterns.guanchazhe;
/**
* FileName: DaoYou
* Author: pengyd
* Date: 2020/7/6
* function: 倒油
*/
public class DaoYou implements Observer{
@Override
public void chaoCai() {
System.out.println("倒油");
}
}
package com.wx.wxjob.designPatterns.guanchazhe;
/**
* FileName: JiaYan
* Author: pengyd
* Date: 2020/7/6
* function: 加盐
*/
public class JiaYan implements Observer{
@Override
public void chaoCai() {
System.out.println("加盐");
}
}
package com.wx.wxjob.designPatterns.guanchazhe;
/**
* FileName: LiaoJiu
* Author: pengyd
* Date: 2020/7/6
* function: 料酒
*/
public class LiaoJiu implements Observer{
@Override
public void chaoCai() {
System.out.println("加料酒");
}
}
package com.wx.wxjob.designPatterns.guanchazhe;
/**
* FileName: ZhuChu
* Author: pengyd
* Date: 2020/7/6
* function:
*/
public class ZhuChu extends Subject{
public void go(){
System.out.println("主厨开始炒菜");
notifyObservers();
}
}
package com.wx.wxjob.designPatterns.guanchazhe;
/**
* FileName: Client
* Author: pengyd
* Date: 2020/7/6
* function:
*/
public class Client {
public static void main(String[] args) {
ZhuChu zhuChu = new ZhuChu();
DaoYou daoYou = new DaoYou();
JiaYan jiaYan = new JiaYan();
LiaoJiu liaoJiu = new LiaoJiu();
zhuChu.attachObserver(daoYou);
zhuChu.attachObserver(jiaYan);
zhuChu.attachObserver(liaoJiu);
zhuChu.go();
}
}
-----------------------------------------------------
主厨开始炒菜
倒油
加盐
加料酒
以上就是利用观察者模式来进行优化的代码过程。
当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象有待改变的时候,应该考虑使用观察者模式。
而使用观察者模式的动机在于:将一个系统分割成一系列相互协作的类有一个很不好的副作用,就是需要维护相关对象间的一致性,我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便,而观察者模式所做的工作就是在解除耦合。
Spring中的ApplicationContext也用到了观察者模式