当前位置: 首页 > news >正文

跟着美团学设计模式(感处)

读了着篇文章之后发现真的是,你的思想,你的思维是真的比比你拥有什么技术要强的。

注 

开闭原则

开闭原则(Open-Closed Principle)是面向对象设计中的基本原则之一,它的定义是:一个软件实体应该对扩展开放,对修改关闭。也就是说,在软件的生命周期内,当需要对软件进行修改时,应该通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

开闭原则的目的是提高软件的可复用性和可维护性。在软件开发过程中,随着业务需求的变化,软件需求可能会发生变化,而开闭原则可以帮助我们避免对现有代码的修改,从而减少引入新错误和重构整个功能的风险

迪米特法则

迪米特法则(Law of Demeter,LoD)是一种面向对象设计原则,也被称为最少知识原则(Least Knowledge Principle,LKP)。它指出一个软件实体应当尽可能少地与其他实体发生相互作用。如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。

迪米特法则的核心思想是降低组件之间的耦合度,提高代码的松耦合性,从而使得代码更易于维护、扩展和重构。在迪米特法则的指导下,一个类应该尽可能少地与其他类发生相互作用,尽量避免直接相互依赖,而是通过接口、抽象类等机制来进行通信,使得类与类之间的联系更加松散,易于维护和扩展。

迪米特法则的命名来源于古希腊神话中的人物狄米特(Demeter),她是希腊神话中的农业女神,也是宙斯的姐姐。在这个神话中,狄米特规定了农业的生产规律,类似于迪米特法则规定了软件实体之间的通信规律。

围绕高内聚和低耦合两个方面,然后结合设计模式

围绕高内聚和低耦合两个方面,然后结合设计模式

围绕高内聚和低耦合两个方面,然后结合设计模式

奖励发放策略

第一天,老师问小明:“你知道活动营销吗?”
“这我知道,活动营销是指企业通过参与社会关注度高的已有活动,或整合有效的资
源自主策划大型活动,从而迅速提高企业及其品牌的知名度、美誉度和影响力,常见
的比如有抽奖、红包等。”
老师点点头:“是的。我们假设现在就要做一个营销,需要用户参与一个活动,然后完
成一系列的任务,最后可以得到一些奖励作为回报。活动的奖励包含美团外卖、酒旅
和美食等多种品类券,现在需要你帮忙设计一套奖励发放方案。”
因为之前有过类似的开发经验,拿到需求的小明二话不说开始了编写起了代码:

 小明很快写好了 Demo,然后发给老师看。
“假如我们即将接入新的打车券,这是否意味着你必须要修改这部分代码?”老师
问道。

一眼就看出了端详。这不满足我们设计原则中的开闭原则,和迪米特原则。

那我们该如何进行优化呢?

这个案例就可以用适配器和策略模式来调优

策略模式 | 菜鸟教程   适配器模式 | 菜鸟教程

先通过这个策略模式优化了变成如下代码

 然后,小明创建策略模式的环境类,并供奖励服务调用:

小明的代码经过优化后,虽然结构和设计上比之前要复杂不少,但考虑到健壮性和拓展性,还是非常值得的。

策略类是有状态的模型吗?如果不是是否可以考虑做成单例的?

环境类的获取策略方法职责很明确,但是依然没有做到完全对修改封闭

解决 :可以将策略类单例化以减少开销,并实现自注册的功能彻底解决分支判断

小明列出单例模式的要点:
单例模式  设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被
创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该
类的对象。

 最终,小明在策略环境类中使用一个注册表来记录各个策略类的注册信息,并提供接
口供策略类调用进行注册。同时使用饿汉式单例模式去优化策略类的设计:

 

 

最终,小明设计完成的结构类图如下:

如果使用了 Spring 框架,还可以利用 Spring 的 Bean 机制来代替上述的部分设计,
直接使用 @Component 和 @PostConstruct 注解即可完成单例的创建和注册,代
码会更加简洁。

一些自己的思考

在设计你的业务逻辑的时候,或者写你的逻辑的代码,一定一定要思考设计模式-创造型模式,结构型模式,和行为型模式,还有下面的

J2EE 模式
这些设计模式特别关注表示层

我们该用什么。怎么调优

任务模型的设计

现在,我想让你去完成任务模型的设计。你需要重点关注状态的流转变更,以及状态变更后的消息通知。而上一个奖励发放策略貌似是状态的一个确定。

小明呢接下了难题,他首先定义了一套任务状态的枚举和行为的枚举

然后,小明对开始编写状态变更功能

很明显上述代码 依然存在有上一个例子的问题。

问题是什么

第一,方法中使用条件判断来控制语句,但是当条件复杂或者状态太多时,条件判
断语句会过于臃肿,可读性差,且不具备扩展性,维护难度也大。且增加新的状态时
要添加新的 if-else 语句,这违背了开闭原则,不利于程序的扩展

第二,任务类不够高内聚,它在通知实现中感知了其他
领域或模块的模型,如活动和任务管理器,这样代码的耦合度太高,不利于扩展

优化

首先是状态流转的控制可以使用状态模式,其次,任务完成时的通知可以用到观察者模式

观察者模式 | 菜鸟教程 状态模式 | 菜鸟教程

根据状态模式的定义,小明将 TaskState 枚举类扩展成多个状态类,并具备完成状
态的流转的能力;然后优化了任务类的实现:

 小明欣喜地看到,经过状态模式处理后的任务类的耦合度得到降低,符合开闭原则。
状态模式的优点在于符合单一职责原则,状态类职责明确,有利于程序的扩展。这样设计的代价是状态类的数目增加了,因此状态流转逻辑越复杂、需要处理的动作
越多,越有利于状态模式的应用。

小明首先设计好抽象目标和抽象观察者,然后将活动和任务管理器的接收通知功能定
制成具体观察者:

 最后,小明将任务进行状态类优化成使用通用的通知方法,并在任务初始态执行状态
流转时定义任务进行态所需的观察者

 

最终,小明设计完成的结构类图如下

 通过观察者模式,小明让任务状态和通知方实现松耦合(实际上观察者模式还没能做到完全的解耦,如果要做进一步的解耦可以考虑学习并使用发布 - 订阅模式)

活动的迭代重构

活动模型的特点在于其组成部分较多,小明原先的活动模型的构建方式是这样的

 

上述代码得问题主要表现在

活动的构造组件较多,导致可以组合的构造函数太多,尤其是在模型增加字段时还需
要去修改构造函数

部分组件的构造存在一定的顺序关系,但是当前的实现没有体现顺序,导致构造逻辑
比较混乱,并且存在部分重复的代码

这种情况呢?我们使用创建者模式。

在实际的应用中,如果字段类型多,
同时各个字段只需要简单的赋值,可以直接引用 Lombok 的 @Builder 注解来实现
轻量的建造者。

重构完活动构建的设计后,小明开始对参加活动方法增加风控。最简单的方式肯定是

直接修改目标方法。但是是有的活动需要风控有的不需要。这时候我们就用了装饰者模式。来进行风控。

相关文章:

跟着美团学设计模式(感处)

读了着篇文章之后发现真的是,你的思想,你的思维是真的比比你拥有什么技术要强的。 注 开闭原则 开闭原则(Open-Closed Principle)是面向对象设计中的基本原则之一,它的定义是:一个软件实体应该对扩展开放…...

2023/8/19 小红书 Java 后台开发面经

项目都做了些什么,怎么实现的用Redis实现了什么,Redis是单线程的吗,Redis是单线程的为什么快,IO多路复用模型具体实现,持久化怎么实现的为什么用Kafka,架构是什么样的,Broker、Topic、Partition…...

基于traccar快捷搭建gps轨迹应用

0. 环境 - win10 虚拟机ubuntu18 - i5 ubuntu22笔记本 - USB-GPS模块一台,比如华大北斗TAU1312-232板 - 双笔记本组网设备:路由器,使得win10笔记本ip:192.168.123.x,而i5笔记本IP是192.168.123.215。 - 安卓 手机 1.…...

【深度学习-图像识别】使用fastai对Caltech101数据集进行图像多分类(50行以内的代码就可达到很高准确率)

文章目录 前言fastai介绍数据集介绍 一、环境准备二、数据集处理1.数据目录结构2.导入依赖项2.读入数据3.模型构建3.1 寻找合适的学习率3.2 模型调优 4.模型保存与应用 总结人工智能-图像识别 系列文章目录 前言 fastai介绍 fastai 是一个深度学习库,它为从业人员…...

Debian10: 安装nut服务器(UPS)

UPS说明: UPS的作用就不必讲了,我选择是SANTAKTGBOX-850,规格为 850VA/510W,可以满足所需,关键是Debian10自带了驱动可以支持,免去安装驱动,将UPS通过USB线连接服务器即可,如下图所示…...

神经网络基础-神经网络补充概念-47-动量梯度下降法

概念 动量梯度下降法(Momentum Gradient Descent)是一种优化算法,用于加速梯度下降的收敛速度,特别是在存在高曲率、平原或局部最小值的情况下。动量法引入了一个称为“动量”(momentum)的概念&#xff0c…...

C++11并发与多线程笔记(13) 补充知识、线程池浅谈、数量谈、总结

C11并发与多线程笔记(13) 补充知识、线程池浅谈、数量谈、总结 1、补充一些知识点1.1 虚假唤醒:1.2 atomic 2、浅谈线程池:3、线程创建数量谈: 1、补充一些知识点 1.1 虚假唤醒: notify_one或者notify_al…...

python高级基础

文章目录 python高级基础闭包修饰器单例模式跟工厂模式工厂模式单例模式 多线程多进程创建websocket服务端手写客户端 python高级基础 闭包 简单解释一下闭包就是可以在内部访问外部函数的变量,因为如果声明全局变量,那在后面就有可能会修改 在闭包中的…...

使用线性回归模型优化权重:探索数据拟合的基础

文章目录 前言一、示例代码二、示例代码解读1.线性回归模型2.MSE损失函数3.优化过程4.结果解读 总结 前言 在机器学习和数据科学中,线性回归是一种常见而重要的方法。本文将以一个简单的代码示例为基础,介绍线性回归的基本原理和应用。将使用Python和Nu…...

亿级短视频,如何架构?

说在前面 在尼恩的(50)读者社群中,经常指导大家面试架构,拿高端offer。 前几天,指导一个年薪100W小伙伴,拿到字节面试邀请。 遇到一个 非常、非常高频的一个面试题,但是很不好回答&#xff0…...

jenkins pipeline方式一键部署github项目

上篇:jenkins一键部署github项目 该篇使用jenkins pipeline-script一键部署,且介绍pipeline-scm jenkins环境配置 前言:按照上篇创建pipeline任务,结果报mvn,jdk环境不存在,就很疑惑,然后配置全…...

Vue 项目搭建

环境配置 1. 安装node.js 官网:nodejs(推荐 v10 以上) 官网:npm 是什么? 由于vue的安装与创建依赖node.js(JavaScript的运行环境)里的npm(包管理和分发工具)&#xff…...

【NetCore】09-中间件

文章目录 中间件:掌控请求处理过程的关键1. 中间件1.1 中间件工作原理1.2 中间件核心对象 2.异常处理中间件:区分真异常和逻辑异常2.1 处理异常的方式2.1.1 日常错误处理--定义错误页的方法2.1.2 使用代理方法处理异常2.1.3 异常过滤器 IExceptionFilter2.1.4 特性过…...

机器学习深度学习——BERT(来自transformer的双向编码器表示)

👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——transformer(机器翻译的再实现) 📚订阅专栏:机器学习&am…...

Datawhale Django后端开发入门 Vscode TASK02 Admin管理员、外键的使用

一.Admin管理员的使用 1、启动django服务 使用创建管理员之前,一定要先启动django服务,虽然TASK01和TASK02是分开的,但是进行第二个流程的时候记得先启动django服务,注意此时是在你的项目文件夹下启动的,时刻注意要执…...

【ES5和ES6】数组遍历的各种方法集合

一、ES5的方法 1.for循环 let arr [1, 2, 3] for (let i 0; i < arr.length; i) {console.log(arr[i]) } // 1 // 2 // 32.forEach() 特点&#xff1a; 没有返回值&#xff0c;只是针对每个元素调用func三个参数&#xff1a;item, index, arr &#xff1b;当前项&#…...

学科在线教育元宇宙VR虚拟仿真平台落实更高质量的交互学习

为推动教育数字化&#xff0c;建设全民终身学习的学习型社会、学习型大国&#xff0c;元宇宙企业深圳华锐视点深度融合VR虚拟现实、数字孪生、云计算和三维建模等技术&#xff0c;搭建教育元宇宙平台&#xff0c;为学生提供更加沉浸式的学习体验&#xff0c;提高学习效果和兴趣…...

[python爬虫] 爬取图片无法打开或已损坏的简单探讨

本文主要针对python使用urlretrieve或urlopen下载百度、搜狗、googto&#xff08;谷歌镜像&#xff09;等图片时&#xff0c;出现"无法打开图片或已损坏"的问题&#xff0c;作者对它进行简单的探讨。同时&#xff0c;作者将进一步帮你巩固selenium自动化操作和urllib…...

vue项目预览pdf功能(解决动态文字无法显示的问题)

最近&#xff0c;因为公司项目需要预览pdf的功能&#xff0c;开始的时候找了市面上的一些pdf插件&#xff0c;都能用&#xff0c;但是&#xff0c;后面因为pdf变成了需要根据内容进行变化的&#xff0c;然后&#xff0c;就出现了需要动态生成的文字不显示了。换了好多好多的插件…...

vue3 样式穿透:deep不生效

初学vue3&#xff0c;今天需要修改el-input组件的属性&#xff08;去掉border和文字居右&#xff09; 网上搜了一下&#xff0c;大致都是采用:deep 样式穿透来修改el-input的属性 <div class"input-container"><el-input placeholder"请输入111&qu…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...