设计模式之观察者模式(java实现事件委托)
1. 简介
观察者模式又叫发布-订阅(Publish/Subscribe)模式。多个观察者对象同时监听一个主题对象,当这个主题对象发生改变时,就会通知所有观察者对象,使它们做出相应的变化。观察者模式其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
2.简单实现一
-
2.1
定义抽象通知者,也就是主题。/** * @Description 抽象通知类 * @Author lijia * @Date 2020/11/4 15:06 */ public abstract class Subject { //通知者状态 protected String status; /** * 增加观察者对象 * @param observer */ abstract void attach(Observer observer); /** * 移除观察者对象 * @param observer */ abstract void remove(Observer observer); /** * 通知实现 */ abstract void notifyVoid(); }
-
2.2
定义抽象观察者,为所有具体观察者定义接口。一般用一个抽象类或接口实现,并包含一个更新方法。/** * @Description 抽象观察者 * @Author lijia * @Date 2020/11/4 15:07 */ public abstract class Observer { /** * 观察者名称 */ protected String name; /** * 主题,通知者 */ protected Subject subject; public Observer(String name, Subject subject) { this.name = name; this.subject = subject; } /** * 定义更新方法 */ abstract void update(); }
-
2.3
定义一个具体通知者。(当老板来了,通知各个员工认真工作。)
/** * @Description 老板 通知者 * @Author lijia * @Date 2020/11/4 15:15 */ public class BossSubject extends Subject { private List<Observer> observerList = new ArrayList<>(); @Override public void attach(Observer observer) { observerList.add(observer); } @Override public void remove(Observer observer) { observerList.remove(observer); } @Override public void notifyVoid() { observerList.forEach(observer -> observer.update()); } }
-
2.4
定义员工A具体观察者,继承抽象观察者类,实现更新接口。/** * @Description 员工A 玩手机的观察者 * @Author lijia * @Date 2020/11/4 15:17 */ public class AObserver extends Observer { public AObserver(String name, Subject subject) { super(name, subject); } @Override public void update() { System.out.println(subject.status + "-" + name + "-不要玩手机,继续工作!"); } }
定义员工B具体观察者,继承抽象观察者类,实现更新接口。
/** * @Description 员工B 打电话观察者 * @Author lijia * @Date 2020/11/4 15:17 */ public class BObserver extends Observer { public BObserver(String name, Subject subject) { super(name, subject); } @Override public void update() { System.out.println(subject.status + "-" + name + "-挂掉电话,继续工作!"); } }
-
2.5
演示/** * @Description * @Author lijia * @Date 2020/11/4 15:26 */ public class Main { public static void main(String[] args) { Subject subject = new BossSubject(); subject.attach(new AObserver("张三", subject)); subject.attach(new AObserver("李双", subject)); subject.attach(new BObserver("王五", subject)); subject.status = "老板回来了"; subject.notifyVoid(); } }
结果打印: 老板回来了-张三-不要玩手机,继续工作! 老板回来了-李双-不要玩手机,继续工作! 老板回来了-王五-挂掉电话,继续工作!
3.简单实现二
利用java1.8新特性函数式接口模拟事件委托实现观察者模式
基本同上,去掉抽象观察者。减少与抽象观察者的耦合问题。
- 3.1
定义函数式接口/** * @Description 定义一个函数式接口 * @Author lijia * @Date 2020/11/4 15:39 */ @FunctionalInterface interface UpdateInvoker { void update(); default void sout() { System.out.println("this is sout"); } }
- 3.2
定义抽象通知者和具体通知者/** * @Description 抽象通知类 * @Author lijia * @Date 2020/11/4 15:06 */ abstract class Subject { protected String status; abstract void attach(UpdateInvoker invoker); abstract void remove(UpdateInvoker observer); abstract void notifyVoid(); } /** * @Description 老板 通知者 * @Author lijia * @Date 2020/11/4 15:15 */ public class BossSubject extends Subject { private List<UpdateInvoker> updateInvokerList = new ArrayList<>(); @Override void attach(UpdateInvoker invoker) { updateInvokerList.add(invoker); } @Override void remove(UpdateInvoker invoker) { updateInvokerList.remove(invoker); } @Override public void notifyVoid() { updateInvokerList.forEach(UpdateInvoker::update); } }
- 3.3
定义观察者/** * @Description 玩手机的观察者 * @Author lijia * @Date 2020/11/4 15:17 */ public class AObserver { private String name; private Subject subject; public AObserver(String name, Subject subject) { this.name = name; this.subject = subject; } public void stop() { System.out.println(subject.status + "-" + name + "-不要玩手机,继续工作!"); } } /** * @Description 打电话观察者 * @Author lijia * @Date 2020/11/4 15:17 */ public class BObserver { private String name; private Subject subject; public BObserver(String name, Subject subject) { this.name = name; this.subject = subject; } public void hangUp() { System.out.println(subject.status + "-" + name + "-挂掉电话,继续工作!"); } }
- 3.4
演示
打印/** * @Description * @Author lijia * @Date 2020/11/4 15:26 */ public class Main { public static void main(String[] args) { BossSubject subject = new BossSubject(); AObserver aObserver = new AObserver("李死", subject); BObserver bObserver = new BObserver("wangwu", subject); subject.status = "boss回来了"; subject.attach(aObserver::stop); UpdateInvoker invoker = bObserver::hangUp; subject.attach(invoker); subject.remove(invoker); subject.notifyVid(); } }
boss回来了-李死-不要玩手机,继续工作!