18 行为型模式-观察者模式

行为模式共有11种:
在这里插入图片描述
观察者模式
模板方法模式
策略模式
职责链模式
状态模式
命令模式
中介者模式
迭代器模式
访问者模式
备忘录模式
解释器模式

以上 11 种行为型模式,除了模板方法模式解释器模式是类行为型模式,其他的全部属于对象行为型模式。

1 观察者模式介绍

在这里插入图片描述
在这里插入图片描述

2 观察者模式原理

在这里插入图片描述
在这里插入图片描述

3 观察者模式实现
/*** 抽象观察者**/
public interface Observer {//update方法: 为不同的观察者更新行为定义一个相同的接口,不同的观察者对该接口有不同的实现public void update();
}
/*** 具体的观察者**/
public class ConcreteObserver1 implements Observer {@Overridepublic void update() {System.out.println("ConcreteObserver1 得到通知,更新状态! !");}
}
public class ConcreteObserver2  implements Observer{@Overridepublic void update() {System.out.println("ConcreteObserver2 得到通知,更新状态! !");}
}
/*** 抽象目标类**/
public interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers();
}
import java.util.ArrayList;/*** 具体目标类**/
public class ConcreteSubject implements Subject {//定义集合,存储所有的观察者对象private ArrayList<Observer> observers = new ArrayList<>();//注册方法,向观察者集合增加一个观察者@Overridepublic void attach(Observer observer) {observers.add(observer);}//注销方法,用于从观察者集合中移除一个观察者@Overridepublic void detach(Observer observer) {observers.remove(observer);}//通知方法@Overridepublic void notifyObservers() {//遍历集合,调用每一个观察者的响应方法for (Observer observer : observers) {observer.update();}}
}
public class Client {public static void main(String[] args) {//创建目标类Subject subject = new ConcreteSubject();//注册观察者,注册多个subject.attach(new ConcreteObserver1());subject.attach(new ConcreteObserver2());//具体的主题内部发生改变,给所有注册的观察者发送通知subject.notifyObservers();}
}
4 观察者模式应用实例

来实现一个买房摇号的程序.摇号结束,需要通过短信告知用户摇号结果,还需要向MQ中保存用户本次摇号的信息.

1 ) 未使用设计模式
/*** 模拟买房摇号服务**/
public class DrawHouseService {//摇号抽签public String lots(String uId){if(uId.hashCode() % 2 == 0){return "恭喜ID为: " + uId + " 的用户,在本次摇号中中签!" ;}else{return "很遗憾,ID为: " + uId + "的用户,您本次未中签!" ;}}
}
/*** 开奖结果封装类**/
public class LotteryResult {private String uId; //用户idprivate String msg; //摇号信息private Date dateTime; //业务时间public LotteryResult(String uId, String msg, Date dateTime) {this.uId = uId;this.msg = msg;this.dateTime = dateTime;}@Overridepublic String toString() {return "LotteryResult{" +"uId='" + uId + '\'' +", msg='" + msg + '\'' +", dateTime=" + dateTime +'}';}public String getuId() {return uId;}public void setuId(String uId) {this.uId = uId;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Date getDateTime() {return dateTime;}public void setDateTime(Date dateTime) {this.dateTime = dateTime;}
}
/*** 开奖服务接口**/
public interface LotteryService {//开奖之后的业务操作public LotteryResult lottery(String uId);}
public class LotteryServiceImpl implements LotteryService {//注入摇号服务private DrawHouseService houseService = new DrawHouseService();@Overridepublic LotteryResult lottery(String uId) {//1.摇号String result = houseService.lots(uId);//2.发短信System.out.println("发送短信通知用户,ID为: " + uId +",您的摇号结果如下: " + result);//3.发送MQ信息System.out.println("记录用户摇号结果到MQ,ID为: " + uId +",摇号结果: " + result);return new LotteryResult(uId,result,new Date());}
}
使用观察者模式进行优化

在这里插入图片描述

/*** 事件监听接口**/
public interface EventListener {//充当观察者的角色,对结果进行监听void doEvent(LotteryResult result);
}
/*** 短信发送事件监听类**/
public class MessageEventListener implements EventListener {@Overridepublic void doEvent(LotteryResult result) {System.out.println("发送短信通知,用户ID: " + result.getuId()+",您的摇号结果为: " + result.getMsg());}
}
/*** MQ消息发送事件监听**/
public class MQEventListener implements EventListener{@Overridepublic void doEvent(LotteryResult result) {System.out.println("记录用户的摇号结果(MQ),用户ID: " + result.getuId()+ ",摇号结果: " + result.getMsg());}
}
/*** 事件处理类**/
public class EventManager {public enum EventType{MQ,Message}//监听器集合Map<Enum<EventType>, List<EventListener>> listeners = new HashMap<>();public EventManager(Enum<EventType>... operations) {for (Enum<EventType> operation : operations) {this.listeners.put(operation,new ArrayList<>());}}/*** 订阅* @param eventType 事件类型* @param listener  监听对象*/public void subscribe(Enum<EventType> eventType,EventListener listener){List<EventListener> users = listeners.get(eventType);users.add(listener);}/*** 取消订阅* @param eventType 事件类型* @param listener  监听对象*/public void unsubscribe(Enum<EventType> eventType,EventListener listener){List<EventListener> users = listeners.get(eventType);users.remove(listener);}/*** 通知* @param eventType* @param result*/public void notify(Enum<EventType> eventType, LotteryResult result){List<EventListener> users = listeners.get(eventType);for (EventListener listener : users) {listener.doEvent(result);}}
}
/*** 开奖服务接口**/
public abstract class LotteryService {private EventManager eventManager;public LotteryService() {//设置事件的类型eventManager = new EventManager(EventManager.EventType.MQ,EventManager.EventType.Message);//订阅eventManager.subscribe(EventManager.EventType.Message,new MessageEventListener());eventManager.subscribe(EventManager.EventType.MQ,new MQEventListener());}public LotteryResult lotteryAndMsg(String uId){LotteryResult lottery = lottery(uId);//发送通知eventManager.notify(EventManager.EventType.Message,lottery);eventManager.notify(EventManager.EventType.MQ,lottery);return lottery;}public abstract LotteryResult lottery(String uId);
}
public class LotteryServiceImpl extends LotteryService {//注入摇号服务private DrawHouseService houseService = new DrawHouseService();@Overridepublic LotteryResult lottery(String uId) {//1.摇号String result = houseService.lots(uId);return new LotteryResult(uId,result,new Date());}
}

测试

@Test
public void test2(){LotteryService ls = new LotteryServiceImpl();LotteryResult result = ls.lotteryAndMsg("1234567887654322");System.out.println(result);
}
5 观察者模式总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/174766.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为eNSP配置专题-策略路由的配置

文章目录 华为eNSP配置专题-策略路由的配置0、概要介绍1、前置环境1.1、宿主机1.2、eNSP模拟器 2、基本环境搭建2.1、终端构成和连接2.2、终端的基本配置 3、配置接入交换机上的VLAN4、配置核心交换机为网关和DHCP服务器5、配置核心交换机和出口路由器互通6、配置PC和出口路由器…

redis archive github

https://github.com/redis/redis/releases/tag/7.2.2https://github.com/redis/redis/releases/tag/7.2.2

塔式服务器介绍

大家都知道服务器分为机架式服务器、刀片式服务器、塔式服务器三类&#xff0c;今天小编就分别讲一讲这三种服务器&#xff0c;第三篇先来讲一讲塔式服务器的介绍。 塔式服务器定义&#xff1a;塔式服务器的外观和普通电脑差不多&#xff0c;直立放置。机箱比较大&#xff0c;服…

高数笔记04:微分方程与多元函数微分学

图源&#xff1a;文心一言 时间比较紧张&#xff0c;仅导图~~&#x1f95d;&#x1f95d; 第1版&#xff1a;查资料、画导图~&#x1f9e9;&#x1f9e9; 参考资料&#xff1a;《高等数学 基础篇》武忠祥 &#x1f9ae;思维导图 &#x1f636;‍&#x1f32b;️思维导图为整…

mysql的医院信息管理系统,数据库增删改查。

基于前端网页和后端服务的&#xff0c;mysql医院信息管理系统。 功能有&#xff1a;登录注册、首页、科室管理、科室列表、医院管理、医生列表、病人管理、护士管理、病房管理、文件管理等等。 并且引入了Echarts图标&#xff0c;可视化查看数据。 源码下载地址 支持&#xff…

Java——Spring的控制反转(一文详解IOC)

Spring&#xff0c;Spring MVC&#xff0c;Spring Boot 三者比较 答&#xff1a; 这三者专注的领域不同&#xff0c;解决的问题也不一样&#xff1b;总的来说&#xff0c;Spring 就像一个大家族&#xff0c;有众多衍生产品例如 Boot&#xff0c;Security&#xff0c;JPA等等。…

DeOldify 接口化改造 集成 Flask

类似的图片修复项目 GFPGAN 的改造见我另一篇文 https://blog.csdn.net/weixin_43074462/article/details/132497146 DeOldify 是一款开源软件&#xff0c;用于给黑白照片或视频上色&#xff0c;效果还不错。 安装部署教程请参考别的文章&#xff0c;本文基于你给项目跑通&…

Flask Run运行机制剖析

一、前言 已经玩了一段时间Flask &#xff0c;每次调用app.run(或flask run)就可以启动应用&#xff0c;今天我们就来了解一下run背后究竟做了些什么事情。 注&#xff1a;通过上面几行代码就可以启动一个Flask服务器&#xff0c;打开浏览器输入http://127.0.0.1:5000, 页面上…

【JVM】类加载器

【JVM】类加载器 文章目录 【JVM】类加载器0. 类加载器概述1. 类加载器的分类1.1 启动类加载器1.2 Java中的默认类加载器1.2.1 扩展类加载器1.2.2 应用程序类加载器 2. 双亲委派机制2.1 类的双亲委派机制是什么&#xff1f;2.2 打破双亲委派机制2.2.1 自定义类加载器2.2.2 线程…

Android多张图片rotation旋转角度叠加/重叠堆放

Android多张图片rotation旋转角度叠加/重叠堆放 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"…

vue中electron与vue通信(fs.existsSync is not a function解决方案)

electron向vue发送消息 dist/main.js (整个文件配置在另一条博客里) win new BrowserWindow({width:1920,height:1080,webPreferences: {// 是否启用Node integrationnodeIntegration: true, // Electron 5.0.0 版本之后它将被默认false// 是否在独立 JavaScript 环境中运行…

【网络协议】聊聊套接字socket

网络编程我们知道是通过socket进行编程的&#xff0c;其实socket也是基于TCP和UDP协议进行编程的。但是在socket层面是感知不到下层的&#xff0c;所以在设置参数的时候&#xff0c;其实是端到端协议智商的网络层和传输层。TCP是数据流所以设置为SOCK_STREAM&#xff0c;而UDP是…

【Linux】——使用yum进行软件安装和卸载Win和Linux文件交互

个人主页点击直达&#xff1a;小白不是程序媛 Linux系列专栏&#xff1a;Linux被操作记 目录 前言&#xff1a; Linux软件包管理器yum 什么是软件包 ​编辑软件查找 如何安装软件 如何卸载软件 lrzsz的使用 将Windows的文件传送到Linux 将Linux的文件传送到Windows …

C++ 自引用指针this(整理)

使用例子&#xff1a; #include <iostream> #include <Windows.h> using namespace std; class A { public:A(int x1){x x1;}void disp(){cout<<"this"<<this<<" when x"<<this->x<<endl;} private:int x;…

Go学习第十四章——Gin请求与响应

Go web框架——Gin请求与响应 1 响应1.1 String1.2 JSON&#xff08;*&#xff09;1.3 HTML&#xff08;*&#xff09;1.4 XML1.5 文件&#xff08;*&#xff09; 2 请求2.1 请求参数查询参数 (Query)动态参数 (Param)表单参数 (PostForm)原始参数 (GetRawData) 2.2 请求头2.3 …

【2023.10.30练习】C语言-循环右移字符

计算机能力挑战初赛2020.19题 题目描述&#xff1a; 现要对一个由字符a-z和A-Z组成的字符串进行解密&#xff0c;已知加密规则是&#xff1a; 字符串中所有字符分别在大写或小写的字母表中被循环左移5位(fGh-->aBc)&#xff0c; 输入&#xff1a;一个加密过的字符串&#…

GO学习之 通道(nil Channel妙用)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

【unity3D】Rect Transform组件

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是unity的Rect Transform组件 Rect Transform组件 基础知识详细介绍补充 基础知识 Rect Transform是Unity中的一个UI组件&#xff0c;用于…

RabbitMQ消费者的可靠性

目录 一、消费者确认 二、失败重试机制 2.1、失败处理策略 三、业务幂等性 3.1、唯一消息ID 3.2、业务判断 3.3、兜底方案 一、消费者确认 RabbitMQ提供了消费者确认机制&#xff08;Consumer Acknowledgement&#xff09;。即&#xff1a;当消费者处理消息结束后&#x…

synchronized 同步锁的思考

经过前面的分析&#xff0c;我们大概对同步锁有了一些基本的认识&#xff0c;同步锁的本质就是实现多线程的互斥&#xff0c;保证同一时刻只有一个线程能够访问加了同步锁的代码&#xff0c;使得线程安全性得到保证。下面我们思考一下&#xff0c;为了达到这个目的&#xff0c;…