目录

代码背景

观察者模式

介绍

实现

观察者(学生)

通知者(老师)

Main方法

委托

介绍

实现

观察者

通知者

事件

事件处理

Main方法

总结


代码背景

一个班级,有两类学生,A类:不学习,玩,但是玩的东西不一样,有的是做游戏,有的是看电视

B类:放哨的学生,专门看老师的动向,如果老师进班了就立即通知大家。

如此就形成了一个需求,放哨的学生要通知所有玩的学生:老师来了,而不同的学生有不同的反应,有的马上把电视关闭,有的停止玩游戏。


观察者模式

介绍

观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
    这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们能够自动更新自己。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。

实现

观察者(学生)

/*** 抽象的观察者** @author Promsing(张有博)* @version 1.0.0* @since 2022/5/10 - 15:32*/
public interface Observer {public abstract void updateState();}/*** 具体的观察者** @author Promsing(张有博)* @version 1.0.0* @since 2022/5/10 - 15:39*/
public class ConcreteObserver implements Observer{//观察者的姓名private String name;//观察者的状态private String observerState;//明确具体的通知者private ConcreteSubject subject;//get set方法省略public ConcreteObserver(String name, ConcreteSubject subject) {this.name = name;this.subject = subject;}@Overridepublic void updateState() {observerState=subject.getSubjectState();System.out.println(name+"在打游戏");String str=String.format("观察者%s的:新状态是%s", name,observerState);System.out.println(str);}
}/*** 具体的观察者** @author Promsing(张有博)* @version 1.0.0* @since 2022/5/10 - 15:39*/
public class ConcreteObserver2 implements Observer{//观察者的姓名private String name;//观察者的状态private String observerState;//明确具体的通知者private ConcreteSubject subject;//get set方法省略public ConcreteObserver2(String name, ConcreteSubject subject) {this.name = name;this.subject = subject;}@Overridepublic void updateState() {observerState=subject.getSubjectState();System.out.println(name+"在看电视");String str=String.format("观察者%s:新状态是%s", name,observerState);System.out.println(str);}
}

通知者(老师)

/*** 抽象的通知者** @author Promsing(张有博)* @version 1.0.0* @since 2022/5/10 - 15:30*/
public abstract class Subject {//管理观察者的集合private List<Observer> observers=new ArrayList<>();//增加观察者public void add(Observer observer){observers.add(observer);}//减少观察者public void detach(Observer observer){observers.remove(observer);}/*** 通知所有的观察者*/public void notifyMsg(){for (Observer observer : observers) {observer.updateState();}}}/*** 具体的通知者** @author Promsing(张有博)* @version 1.0.0* @since 2022/5/10 - 15:38*/
public class ConcreteSubject extends Subject {//通知者的状态private String subjectState;//get set方法public String getSubjectState() {return subjectState;}public void setSubjectState(String subjectState) {this.subjectState = subjectState;}
}

Main方法

/*** 控制台Main方法** @author Promsing(张有博)* @version 1.0.0* @since 2022/5/10 - 15:48*/
public class MainTest {public static void main(String[] args) {//创建一个主题/通知者ConcreteSubject subject=new ConcreteSubject();//new出观察者(学生)ConcreteObserver studentZhang = new ConcreteObserver("小张", subject);ConcreteObserver studentLiu = new ConcreteObserver("小刘", subject);ConcreteObserver studentWang = new ConcreteObserver("小王", subject);//将观察者添加到通知队列里subject.add(studentZhang);subject.add(studentLiu);subject.add(studentWang);//通知者(老师)状态修改,通知每个学生subject.setSubjectState("老师回来了,我要好好学习");subject.notifyMsg();System.out.println("-----------");}}


委托

介绍

委托可以看做是函数的抽象,是函数的“类”。委托的实例将代表一个具体的函数
一个委托可以搭载多个方法,所有的方法被依次唤起。可以使委托对象所搭载的方法并不需要属于同一类。
委托事件模型可以由三个组件定义:事件、事件源和事件侦听器。

委托的实现简单来讲就是用反射来实现的。

实现

观察者

/*** 监听器/观察者 玩游戏* 事件监听器* @author Promsing(张有博)* @version 1.0.0* @since 2022/5/8 - 11:17*/
public class PlayingGameListener {public PlayingGameListener(){System.out.println("我正在玩游戏 开始时间"+new Date());}public void stopPlayingGame(Date date){System.out.println("老师来了,快回到座位上,结束时间"+date);}}/*** 监听器/观察者 看电视* 事件监听器* @author Promsing(张有博)* @version 1.0.0* @since 2022/5/8 - 11:17*/
public class WatchingTVListener {public WatchingTVListener(){System.out.println("我正在看电视 "+new Date());}public void stopWatchingTV(Date date){System.out.println("老师来了,快关闭电视 。 结束时间"+date);}}

通知者

/*** 通知者的抽象类* 事件源* @author Promsing(张有博)* @version 1.0.0* @since 2022/5/8 - 11:15*/
public abstract class Notifier {//每个通知者都有一个需要通知的队列(通知:对象、方法、参数)private EventHandler eventHandler=new EventHandler();public EventHandler getEventHandler() {return eventHandler;}public void setEventHandler(EventHandler eventHandler) {this.eventHandler = eventHandler;}//增加需要帮忙放哨的学生public abstract void addListener(Object object,String methodName,Object...args);//告诉所有要帮忙放哨的学生:老师来了public abstract void notifyX();
}/*** 通知者的子类,放哨人* 事件源* @author Promsing(张有博)* @version 1.0.0* @since 2022/5/8 - 11:15*/
public class GoodNotifier extends Notifier {@Overridepublic void addListener(Object object, String methodName, Object...args) {System.out.println("有新的同学委托尽职尽责的放哨人!");this.getEventHandler().addEvent(object, methodName, args);}@Overridepublic void notifyX() {System.out.println("尽职尽责的放哨人告诉所有需要帮忙的同学:老师来了");try{//优化:异步通知this.getEventHandler().notifyX();}catch(Exception e){e.printStackTrace();}}
}

事件

/*** 抽象出的事件类,也可以称为方法类* 事件* @author Promsing(张有博)* @version 1.0.0* @since 2022/5/8 - 11:03*/
public class Event {//要执行方法的对象private Object object;//要执行的方法名称private String methodName;//要执行方法的参数private Object[] params;//要执行方法的参数类型private Class[] paramTypes;//若干setter getterpublic Object getObject() {return object;}public String getMethodName() {return methodName;}public void setMethodName(String methodName) {this.methodName = methodName;}public Object[] getParams() {return params;}public void setParams(Object[] params) {this.params = params;}public Class[] getParamTypes() {return paramTypes;}public void setParamTypes(Class[] paramTypes) {this.paramTypes = paramTypes;}public Event(){}public Event(Object object,String methodName,Object...args){this.object=object;this.methodName=methodName;this.params=args;contractParamTypes(this.params);}//根据参数数组生成参数类型数组private void contractParamTypes(Object[] params){this.paramTypes=new Class[params.length];for(int i=0;i<params.length;i++){this.paramTypes[i]=params[i].getClass();}}//执行该 对象的该方法public void invoke() throws Exception{//通过class,method,paramTypes 确定执行哪个类的哪个方法Method method=object.getClass().getMethod(this.getMethodName(), this.getParamTypes());if(null==method){return;}//方法执行method.invoke(this.getObject(), this.getParams());}}

事件处理

/*** 管理哪些事件需要执行* 管理事件** @author Promsing(张有博)* @version 1.0.0* @since 2022/5/8 - 11:03*/
public class EventHandler {//是用一个Listprivate List<Event> objects;//添加某个对象要执行的事件,及需要的参数public void addEvent(Object object,String methodName,Object...args){objects.add(new Event(object,methodName,args));}public EventHandler(){objects=new ArrayList<Event>();}//通知所有的对象执行指定的事件public void notifyX() throws Exception{for(Event e : objects){e.invoke();}}
}

Main方法

/*** 启动类** @author Promsing(张有博)* @version 1.0.0* @since 2022/5/8 - 11:19*/
public class EventMain {public static void main(String[] args) {//创建一个尽职尽责的放哨者Notifier goodNotifier = new GoodNotifier();//创建一个玩游戏的同学,开始玩游戏PlayingGameListener playingGameListener = new PlayingGameListener();//创建一个看电视的同学,开始看电视WatchingTVListener watchingTVListener = new WatchingTVListener();//玩游戏的同学告诉放哨的同学,老师来了告诉一下goodNotifier.addListener(playingGameListener, "stopPlayingGame", new Date());//看电视的同学告诉放哨的同学,老师来了告诉一下goodNotifier.addListener(watchingTVListener, "stopWatchingTV", new Date());try {//一点时间后Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}//老师出现,放哨的人通知所有要帮忙的同学:老师来了goodNotifier.notifyX();}
}


总结

1.先有观察者模式后有委托事件技术
2.观察者模式只能通知继承 Observer类 的子类,也可以将Observer改成接口

for (Observer observer : observers) {observer.updateState();
}

3.委托可以通知任何类的任何方法。反射、everone

    Method method=object.getClass().getMethod(this.getMethodName(), this.getParamTypes());if(null==method){return;}method.invoke(this.getObject(), this.getParams());

4.委托与观察者比多了一个事件执行者,解除观察者与通知者的耦合,可以做到通知任何对象的任何方法。让A类学生和B类学生完全解耦,即A类完全不知道B类的学生,却可以通知B类的学生

6.建立一套触发机制,可以使用异步通知

7.观察者/委托挺像MQ里边的订阅发布。生产者、队列、消费者。

Java中观察者模式与委托的对比相关推荐

  1. Java中的queue和deque对比详解

    队列(queue)简述 队列(queue)是一种常用的数据结构,可以将队列看做是一种特殊的线性表,该结构遵循的先进先出原则.Java中,LinkedList实现了Queue接口,因为LinkedLis ...

  2. Java中this和super的对比

    使用super的注意事项 super调用父类的构造方法,必须写在构造方法中第一个 super只能出现在子类的方法中 super和this不能同时使用构造方法,因为这两个都要求必须写在构造方法中第一个 ...

  3. Java中各种比较对象方式对比

    1.介绍 比较对象是面向对象编程语言的一个基本特征.在本教程中,我们将介绍Java语言的一些特性,这些特性允许我们比较对象.此外,我们还将研究外部库中的这些特性. 2.==和!=操作符 让我们从==和 ...

  4. java 中long型数据的对比

    在对比之前先看一个程序吧 Long a = new Long(3);Long b = new Long(3);System.out.println(a.equals(b));Long c = new ...

  5. java中审核订单流程图_Java 后端横扫阿里、滴滴、美团总结的面试经验!

    这次面试的公司有一点点多,主要是因为毕业后前两份工作找的都很草率,这次换工作就想着,emm,毕业三年了,该找个工作好好沉淀几年了. 先说下这次面试的结果吧: 到 hr 面的:阿里.美团.滴滴.金山云. ...

  6. java中审核订单流程图_看95后java妹子横扫阿里,京东,小米,滴滴,美团等大厂,一份热腾腾的面经(最终入职阿里)...

    内容目录 头条 美团 滴滴 京东 others 算法题 HR面 tips 自序 这次面试的公司有一点点多,主要是因为毕业后前两份工作找的都很草率,这次换工作就想着,emm,毕业三年了,该找个工作好好沉 ...

  7. Java中容易被遗忘的default关键字

    default关键字 default关键字在JDK8中有两个用处. 1.在switch语句的时候使用default int day = 8; String dayString; switch (day ...

  8. JAVA面试要点006---.net中的委托与java中的代理模式和委托

    1.1.1 定义 委托是一种引用方法的类型.一旦为委托分配了方法,委托将与该方法具有完全相同的行为.委托方法的使用可以像其他任何方法一样,具有参数和返回值,如下面的示例所示: //Code in C# ...

  9. Java中使用Observer接口和Observable类实践Observer观察者模式

    在Java中通过Observable类和Observer接口实现了观察者模式.实现Observer接口的对象是观察者,继承Observable的对象是被观察者. 1. 实现观察者模式 实现观察者模式非 ...

  10. C#、C++、JAVA中虚函数和抽象函数的概念对比

    这两天恶补了下C#的相关内容,虚函数的概念又挖掘了下,总结如下: 1.C++中函数被定义为虚函数的方法是在函数名前加virtual,虚函数可以有自己的具体内容,也可以不含有函数实现内容,称为纯虚函数. ...

最新文章

  1. R构建加权最小二乘回归模型(Weighted Least Squares Regression)
  2. pytorch按维度取数据0917
  3. [Nodejs原理] 核心库Libuv入门(Hello World篇)
  4. vue组件化通信之父向子传值
  5. python定义模块结束语_python-模块定义、导入、优化
  6. Objective-c 中 nil, Nil, NULL和NSNull的区别
  7. vgremore 删除卷组
  8. 英伟达显卡不同架构_架构定输赢!盘点历代英伟达显卡能够成功亥市的根源
  9. CuteFtp通用注册码
  10. 可以搜python题答案的app-有哪些可以搜Python题答案的APP
  11. Oracle 购买价格 和 服务费 计算方式
  12. 大一学生《web课程设计》用DIV+CSS技术设计的个人网页(网页制作课作业)
  13. 数据结构哈希表的基本操作(C语言)
  14. 禁用Insert按键
  15. 支付宝AR实景红包寻宝攻略
  16. 硬链接、软链接、ln命令
  17. java 获取百度云盘图片_java 利用百度云识别图片文字
  18. EBS 打印机设置——PASTA
  19. C#项目:未找到引用错误解决方案
  20. java 向上转型与向下转型

热门文章

  1. C++模板技术实现 泛型编程,通俗易懂的泛型编程教程//。
  2. 2022年信息安全工程师考试知识点:访问控制
  3. 2022年信息安全工程师考试知识点:计算机网络基本知识
  4. 3D打印的四种应用场合
  5. android模拟器脚本,安卓模拟器脚本制作工具
  6. 用友U8打开起初采购入库单报错
  7. 第三代计算机的内存是,Intel正式发布Cooper Lake、第三代傲腾内存和新数据中心SSD...
  8. NiFi+Kylo安装部署
  9. 基于DMD实现透过多模光纤(MMF)的聚焦
  10. java将数字转换成大写_Java中金额数字转换为大写数字