构建器模式Builder
分步骤创建复杂对象(有众多复杂参数,基本让人看不懂的构造函数)。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 构造者模式最核心的思想就是将创建复杂对象的过程与复杂对象本身进行拆分。通俗来讲,构造者模式是将复杂对象的创建过程分解成了多个简单步骤,在创建复杂对象的时候,只需要了解复杂对象的基本属性即可,而不需要关心复杂对象的内部构造过程。这样的话,使用方只需要关心这个复杂对象要什么数据,而不再关心内部细节。 每个属性有自己的build方法。 作用1:其他对象不能访问正在创建的产品 作用2:可以实现链式编程(返回自己的ElementBuiler对象) 作用3:不需要调用所有的步骤 最后build 的时候返回真正Element的结果,可以实现链式编程 构造者模式的四个核心组件: Product 接口:复杂对象的接口,定义了要创建的目标对象的行为。 ProductImpl 类:Product 接口的实现,它真正要创建的复杂对象,其中实现了我们需要的复杂业务逻辑。 Builder 接口:定义了构造 Product 对象的每一步行为。 BuilderImpl 类:Bu...
桥接Bridge
分离抽象与具体实现,让他们可以独自发展 用聚合代替继承的方式连接抽象和具体 https://refactoringguru.cn/design-patterns/bridge 应用1Gift -> WarmGift ColdGift WildGift GiftImpl -> Flower Ring Car 最终抽象类(Gift)的精确抽象(WarmGift) 里面组合了 实现类(GiftImpl)的 具体实现(Flower) 应用2还有一个遥控和播放器的例子。两个都是接口,遥控是抽象类,播放器是实现类,播放器不包含遥控,但是遥控要控制播放器就要组合播放器。电视遥控组合电视,广播遥控组合广播 代码实现: https://refactoringguru.cn/design-patterns/bridge/java/example#example-0--remotes-Remote-java
模板方法TemplateMethod
就是钩子函数 模板已经写好了 重写方法,系统自动调用,都是模板方法 使用的时候面向接口编程,这就是模板方法 在我们开发业务逻辑的时候,可能会遇到流程复杂的逻辑,而这个复杂逻辑本身是可以拆解成多个小的行为,这些小的行为本身可能根据业务场景的不同而有所变化。 这里我们以转账流程为例,如下图所示,整个转账流程是固定的,但是“验证密码”“验证余额”和“扣除金额”这三步针对不同的银行卡,要调用不同银行的接口去完成。为了让整个复杂流程的代码具有更好的扩展性,我们一般会使用模板方法模式来处理。 在模板方法模式中,我们可以将复杂流程中每个步骤的边界确定下来,然后由一个“模板方法”定义每个步骤的执行流程,每个步骤对应着一个方法,这些方法也被称为“基本方法”。模板方法按照业务逻辑依次调用上述基本方法,来实现完整的复杂流程。 模板方法模式会将模板方法以及**不需要随业务场景变化的基本方法放到父类中实现,随业务场景变化的基本方法会被定义为抽象方法,由子类提供真正的实现。** 下图展示了模板方法模式的核心类,其中 template() 方法是我们上面描述的模板方法,part1() 方法和 part3()...
消息端到端的一致性与可靠性
TCP其实自带超时重传机制,保证了消息可靠性的传输,那么为什么我们还要再去讨论和实现 消息可用 呢? TCP究竟帮助我们做到哪一步? 客户端A 发送 msg1和msg2两个消息给到服务端。 msg1和msg2在一个tcp链接上到达服务端。 理论上来说,msg1 和 msg2 是遵循顺序从客户端 A 发送到服务端的,似乎消息是一定收到的,但是这其实是一个端到端可靠性的问题,TCP 作为传输层协议,只能说消息可靠到达了传输层,但是不能说消息可靠到达了业务层。 问题 在传递给业务层时服务端进程崩溃,但客户端A认为已经送达,服务端业务层无感知, 自然无法发送到客户端 B,因此消息丢失。 msg1和msg2到达应用层, 解析后交由两个线程处理, 可能msg2 消息体小一些,msg1 消息体大一些,导致了m2 先解析完毕,落表后先发送给客户端 B, 造成消息乱序。 msg1消息存储失败,msg2消息存储成功先发送给了客户端B,造成丢失且乱序。 !!! tips 洞见: TCP/UDP是双方通信 (本质上是 C/S 模式),而IM本质上是三方通信。 技术...
案例分析-DNS+tcpdump+wireshark
网络优化,实际上包含了整 个网络协议栈的所有层的优化。 DNS解析速度不稳定 DNS(Domain Name System) 域名系统,提供 域名和 IP 地址之间映射关系的查询服务。动态服务发现和全局 负载均衡(Global Server Load Balance,GSLB)的机制。这样,DNS 就可以选择离用户 最近的 IP 来提供服务。即使后端服务的 IP 地址发生变化,用户依然可以用相同域名来访 问。 域名。位置越靠后,层级越高。 com 是顶级域名, yuque 是二级域名 域名解析服务 (DNS),而对应的服务器就是域名服务器,网络协议则是 DNS 协议。DNS 协议在 TCP/IP 栈中属于应用层,不过实际传输还是基于 UDP 或者 TCP 协议(UDP 居多) ,并且域名服务器一般监听在端口 53 上。 在配置 Linux 系统的网络时,需要给它配置 DNS 服务器,这样它才可以通过域名来访问外部服务。 另外,DNS 服务**通过资源记录的方式,来管理所有数据,它支持 A、CNAME、MX、 NS、PTR 等多种类型的记录**。比如: A 记录,...
消息队列
为什么主要作用: 异步:提高系统响应速度以及吞吐量 削峰填谷:稳定平滑系统流量 解耦:减少服务之间的影响,提高系统整体的稳定性以及扩展性 主要缺点MQ 是基于事件驱动的。消息由生产者发送到MQ进行排队,然后按FIFO的顺序交由消息的消费者进行处理。其主要缺点: 系统可用性降低:外部依赖增加,稳定性变差,要考虑MQ的高可用 系统复杂度提高:消息链路追踪复杂,顺序也要保证 消息一致性问题 怎么用(生产环境关注公有云服务)公有云产品官网消息队列全景:https://www.aliyun.com/product/ons?spm=5176.23056729.J_3207526240.58.3dcc3f06fc3SNi MQTT 是给车联网使用, 适合消息比较小且多的跨端消息传输 rabbit 主要是为了原有使用 rabbit 的项目快速迁移,以及增强了 rabbitMQ 的稳定性,降低了运维的成本 kafka 主要用来给大数据日志分析使用, eventBridge 主要用来给 SaaS 平台提供事件总线的能力,实现不同系统之间的解耦以及数据的事件通知机制。如果平台和 Even...
消息队列重点问题
参考资料: 从 0 开始带你成为消息中间件实战高手 中华石杉互联网 Java 工程师面试突击(第一季) 重点 一定要在自己的核心链路里做文章,有没有可能一个关键的步骤会失败?如果这个关键步骤失败了,这个时候会怎么样?如果某个步骤没有成功,是不是需要启动后台线程定时扫描进行补偿? 所谓的核心链路,不是说查询链路,即并不是一次请求全部是查询。而是说的是数据更新链路,即一次请求过后会对你的各种核心数据进行更新,同时还会调用其他服务或者系统进行数据更新或者查询,这样的一个链路叫做系统的核心链路。针对这样的系统核心数据链路,你考虑一下有没有哪些环节拖累了性能?你能否通过在系统里打印日志的方式,排查出来核心数据链路中的每个环节的耗时是多长?哪些环节是最耗时的?有没有可能引入MQ技术把一些耗时的步骤做成异步化的方式,来优化核心数据链路的性能?如果可以的话,你应该如何设计这个技术方案?哪些环节同步执行?哪些环节要异步执行? 主动思考能力,随机应变的本事。 如果让你写一个消息队列,该如何进行架构设计?说一下你的思路。从整体了解把握住一个消息队列的架构原理,给出一些关键点出来。技术的基本原理、...
状态模式State
根据状态决定动作 不同状态下的同一动作有不同的实现,就是一个简单的多态。简单面向接口编程 应用:TCP 不同的状态下open close ack的方法的实现是不一样的,扩展方法是不方便的,方法不扩展可以使用状态模式 线程状态案例 线程是上下文 线程状态是State Running,Blocking等等是具体的状态 状态接口1234public abstract class ThreadState_ { abstract void move(Action input); abstract void run();} 具体状态123456789101112131415161718public class NewState extends ThreadState_ { private Thread_ t; public NewState(Thread_ t) { this.t = t; } @Override void move(Action input) { ...
用例图+用例描述表
描述 用户、需求、系统功能单元 之间的关系。它展示了一个外部用户能够观察到的系统功能模型图。 帮助开发团队以一种可视化的方式理解系统的功能需求。 参与者,Actor,一般一个小人 用例,Use Case , 外部用户可见的系统功能,对系统的功能进行描述,椭圆表示 子系统, (模块)展示系统的一部分功能,内部功能紧密联系 关系(具体参见UML,基本一致) 依赖:指向被依赖项 关联:指向消息接收方 泛化:指向父用例 包含:指向分解出来的功能用例 扩展:指向基础用例(附加功能) 项目Artifact,用例关联的具体说明 注释 用例描述表: 参考:https://blog.csdn.net/suxinpingtao51/article/details/8011335?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-ta...
消灭重复代码的最佳实践
代码重复本身不可怕,可怕的是漏改或改错。消灭重复代码,降低改动可能引入的风险。 学习笔记:https://time.geekbang.org/column/article/228964 工厂模式 + 模板方法 消除 if else 和重复代码假设要开发一个购物车下单的功能,针对不同用户进行不同处理: 普通用户需要收取运费,运费是商品价格的 10%,无商品折扣; VIP 用户同样需要收取商品价格 10% 的快递费,但购买两件以上相同商品时,第三件开始享受一定折扣; 内部用户可以免运费,无商品折扣。 我们的目标是实现三种类型的购物车业务逻辑,把入参 Map 对象(Key 是商品 ID,Value 是商品数量),转换为出参购物车类型 Cart。 原始代码12345678910111213141516171819202122232425262728//购物车@Datapublic class Cart { //商品清单 private List<Item> items = new ArrayList<>(); //总优惠 ...