热门标签 | HotTags
当前位置:  开发笔记 > 程序员 > 正文

我的设计模式之旅③职责链模式

一个菜鸟的设计模式之旅,文章可能会有不对的地方,恳请大佬指出错误。编程旅途是漫长遥远的,在不同时刻有不同的感悟,本文会一直更新下去。程序介绍本程序实现职责链模式,现有三批不同重

一个菜鸟的设计模式之旅,文章可能会有不对的地方,恳请大佬指出错误。

编程旅途是漫长遥远的,在不同时刻有不同的感悟,本文会一直更新下去。


程序介绍

本程序实现职责链模式,现有三批不同重量的货物,有三种工具可以托运,分别是自行车、汽车、卡车,未来工具可能会增多,判断这些货物由哪个工具运输。

PS C:\Users\小能喵喵喵\Desktop\设计模式\职责链模式> go run .
自行车拉货 5 kg
卡车拉货 500 kg
汽车拉货 200 kg

程序代码

chainOfResponsibility.go

package main
import "fmt"
type Handler interface {
HandleRequest(weight float64)
SetSuccessor(successor Handler)
}
type handler struct {
successor Handler
}
func (h *handler) SetSuccessor(successor Handler) {
h.successor = successor
}
type Truck struct {
handler
}
type Car struct {
handler
}
type Bike struct {
handler
}
func (t *Truck) HandleRequest(weight float64) {
if weight <= 3000 {
fmt.Printf("卡车拉货 %v kg\n", weight)
} else {
if t.successor != nil {
t.successor.HandleRequest(weight)
}
}
}
func (c *Car) HandleRequest(weight float64) {
if weight <= 200 {
fmt.Printf("汽车拉货 %v kg\n", weight)
} else {
if c.successor != nil {
c.successor.HandleRequest(weight)
}
}
}
func (b *Bike) HandleRequest(weight float64) {
if weight <= 10 {
fmt.Printf("自行车拉货 %v kg\n", weight)
} else {
if b.successor != nil {
b.successor.HandleRequest(weight)
}
}
}

handler结构体是所有工具的基类,抽象出了共同的属性和设置后继者行为。

Handler接口实现鸭子类型,用于确保具体处理者有效,必须实现两种必要的方法,客户端通过声明Handler接口去实例化具体处理者(里氏代换原则),当处理者添加,比如飞机空运,不会影响到客户端代码模块。


main.go

package main
func main() {
var truck Handler = &Truck{}
var car Handler = &Car{}
var bike Handler = &Bike{}
bike.SetSuccessor(car)
car.SetSuccessor(truck)
// 第一批货
bike.HandleRequest(5)
// 第二批货
bike.HandleRequest(500)
// 第三批货
bike.HandleRequest(200)
}

Console

PS C:\Users\小能喵喵喵\Desktop\设计模式\职责链模式> go run .
自行车拉货 5 kg
卡车拉货 500 kg
汽车拉货 200 kg

思考总结

什么是职责链模式

image-20220909113450487


职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。这种类型的设计模式属于行为型模式。


如果没有职责链模式,当处理者增多或修改时,会违背开放-封闭原则,不容易维护,不灵活。类有太多责任,导致不够灵活。可以利用多态性、职责链模式化解分支带来的僵化。

//管理者类处理请求伪代码
switch 请求{
条件1 :
方法A处理(请求)
条件2 :
方法B处理(请求)
条件3 :
方法C处理(请求)
}

意图:责任链模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦(发出请求的客户端并不知道哪一个对象最终会处理这个请求,它只管发请求,这样可以再不影响客户端的情况下动态组织请求处理者,重新分配责任)。通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。每个处理者仅需保持一个指向其后继者的引用,而不需保持它所有的候选者的引用,大大降低耦合度。

主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

如何解决:拦截的类都实现统一接口。

关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。

应用实例: 1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。

优点:



  • 降低耦合度。它将请求的发送者和接收者解耦。

  • 简化了对象。使得对象不需要知道链的结构。

  • 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。

  • 增加新的请求处理类很方便。

缺点:



  • 不能保证请求一定被接收。一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理。

  • 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。

  • 可能不容易观察运行时的特征,有碍于除错。

使用场景:



  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

  • 可动态指定一组对象处理请求。


参考资料

  • 《Go语言核心编程》李文塔

  • 《Go语言高级编程》柴树彬、曹春辉

  • 《大话设计模式》程杰

  • 单例模式 | 菜鸟教程



推荐阅读
  • 十大算法书籍助力编程之路
    算法作为编程学习的核心技能,其重要性不容忽视。虽然算法的学习难度较高,但其对提升编程能力、通过技术面试以及应对当前热门的技术领域如人工智能和区块链等都有着不可替代的作用。本文精选十本算法书籍,旨在帮助程序员更好地掌握这一关键技术。 ... [详细]
  • Canvas漫游:碰撞检测与动画模拟
    探索Canvas在Web开发中的应用,通过碰撞检测与动画模拟提升交互体验。 ... [详细]
  • 在Python编程中,eval()函数是一个强大的工具,用于执行字符串形式的Python表达式并返回其计算结果。本文将深入探讨eval()函数的基本用法及其潜在的安全风险,帮助读者在实际应用中更加谨慎和高效地使用这一功能。 ... [详细]
  • 利用RabbitMQ实现高效延迟任务处理
    本文详细探讨了如何利用RabbitMQ实现延迟任务,包括其应用场景、实现原理、系统设计以及具体的Spring Boot实现方式。 ... [详细]
  • MySQL数据误删应急处理与预防策略
    本文提供了关于如何应对MySQL数据库中数据误删情况的详细指导,并分享了一些有效的预防措施,帮助数据库管理员减少误操作带来的损失。 ... [详细]
  • 本文精选了 GitHub 上由个人维护且获得大量 Star 的 Spring Boot 学习项目,适合初学者和技术爱好者参考。 ... [详细]
  • 本文档旨在帮助开发者回顾游戏开发中的人工智能技术,涵盖移动算法、群聚行为、路径规划、脚本AI、有限状态机、模糊逻辑、规则式AI、概率论与贝叶斯技术、神经网络及遗传算法等内容。 ... [详细]
  • 本文介绍了如何计算给定数组中所有非质数元素的总和,并提供了多种编程语言的实现示例。 ... [详细]
  • 详解 | 日志系统ViseLog的基本使用与功能
    本文详细介绍了日志系统ViseLog的使用方法及其核心功能,旨在帮助开发者更好地理解和利用这一工具,提高开发效率。 ... [详细]
  • 了解如何在Java面试中有效地讨论薪资问题,不仅能够帮助求职者更好地表达自己的价值,还能增加成功入职的机会。 ... [详细]
  • 探讨在构建类似Viber或WhatsApp的聊天应用时,如何有效实现客户端(Web、Android、iOS)与服务器之间的连接。本文将分析使用WebSockets标准及其替代方案的优劣。 ... [详细]
  • 单例模式是软件开发中常用的设计模式之一,用于确保一个类只有一个实例,并提供一个全局访问点。本文探讨了在单例模式实现中使用volatile关键字的重要性,特别是在懒汉模式下的应用。 ... [详细]
  • 探讨了在使用客户端JavaScript时,确保其完整性和来源可靠性的方法,特别是在安全性要求较高的应用中。 ... [详细]
  • Python基础教程:struct模块与格式化字符详解
    本文详细介绍了Python中struct模块的功能,以及如何利用格式化字符实现Python与C语言结构体之间的数据转换。文章通过具体实例讲解了struct模块的主要方法及其应用场景。 ... [详细]
  • 大数据性能评估指南
    本文档旨在介绍大数据性能评估的基本概念,详细描述了进行大数据基准测试的步骤,包括数据准备、负载选择以及指标度量等关键环节。 ... [详细]
author-avatar
书友23295799
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有