《golang设计模式》第三部分·行为型模式-01-责任链模式(Chain of Responsibility)

文章目录

  • [1 概念](#1 概念)
    • [1.1 角色](#1.1 角色)
    • [1.2 类图](#1.2 类图)
  • [2. 代码示例](#2. 代码示例)
    • [2.1 设计](#2.1 设计)
    • [2.2 代码](#2.2 代码)
    • [2.3 类图](#2.3 类图)

1 概念

责任链(Chain of Responsibility)是指将客户端请求处理的不同职责对象组成请求处理链。

客户端只需要将请求交付到该链上,而不需要关心链上含有哪些对象。请求处理链上的对象收到请求后,执行自身业务职责,并将该请求传递到下一个链节点。由于客户端不需要了解责任链上节点对象的具体类型,大大降低了客户端与请求处理对象之间的耦合度。

1.1 角色

抽象处理者(Handler):包含抽象处理方法和一个后续处理者。

具体处理者(ConcreteHandler):实现抽象处理者的处理方法。

请求发送者(Client):向处理者发送请求。

1.2 类图

Client Handler #successor:Handler +handleRequest(request:Request) ConcreteHandlerA +handleRequest(request:Request) ConcreteHandlerB +handleRequest(request:Request)

2. 代码示例

2.1 设计

  • 定义一个抽象处理者Handler
  • 定义实际处理者ConcreteHandlerAConcreteHandlerB
    • 它们实现了抽象处理者Handler
    • 它继承了另一个处理者(下一个处理者)
    • 它的Option()方法执行它的责任
    • 它的handleRequest()方法组装责任链并执行它的责任
  • 调用
    • 实例化三个实际处理者
    • 使用handleRequest()方法执行责任链

2.2 代码

go 复制代码
package main

import (
	"fmt"
)

// 定义抽象处理者
type Handler interface {
	handleRequest() string
}

// 定义实际处理者A
type ConcreteHandlerA struct {
	name string
	next Handler
}
//定义一个方法模拟实际处理者A的处理过程
func (c *ConcreteHandlerA) Option() {
	fmt.Println("执行:" + c.name)
}
//定义一个方法,完成它的处理后,交给下一个实际处理者
func (c *ConcreteHandlerA) handleRequest() string {
	c.Option()
	if c.next != nil {
		return c.next.handleRequest()
	}
	return ""
}

// 定义实际处理者B(情况和A相同)
type ConcreteHandlerB struct {
	name string
	next Handler
}

func (c *ConcreteHandlerB) Option() {
	fmt.Println("执行:" + c.name)
}

func (c *ConcreteHandlerB) handleRequest() string {
	c.Option()
	if c.next != nil {
		return c.next.handleRequest()
	}
	return ""
}

//定义一个函数,生产处理者
func NewHandler(name string, next Handler, kind string) (handler Handler, err error) {
	switch kind {
	case "A":
		handler = &ConcreteHandlerA{
			name: name,
			next: next,
		}
		return handler, nil
	case "B":
		handler = &ConcreteHandlerB{
			name: name,
			next: next,
		}
		return handler, nil
	default:
		return nil, err
	}

}


func main() {
	//实例化3个实际处理者
	handlerA1, _ := NewHandler("handlerA1", nil, "A")
	handlerA2, _ := NewHandler("handlerA2", handlerA1, "A")
	handlerB1, _ := NewHandler("handlerB1", handlerA2, "B")
    //使用handleRequest方法依次处理(处理过程我们不可见,但是可以通断点过调试看到)
	r := handlerB1.handleRequest()
	fmt.Println(r)
}
  • 执行结果
shell 复制代码
执行:handlerB1
执行:handlerA2
执行:handlerA1

2.3 类图

Client <<interface>> Handler +handleRequest() : string ConcreteHandlerA +name:string +next:Handler +handleRequest() : string +Option() ConcreteHandlerB +name:string +next:Handler +handleRequest() : string +Option()


相关推荐
EMA34 分钟前
Docker虚拟化失败解决方案
架构
李斯维1 小时前
从历史的角度看 Android 软件架构
android·架构·android jetpack
JouYY3 小时前
聊一下多 Agent 编排架构的应用实践
架构·llm·agent
Sunia4 小时前
《AgentX 专栏》10-生产部署:3台2C4G云服务器把企业级Agent真正跑起来的完整方案
java·架构
ZhengEnCi1 天前
Q01-高并发点赞系统架构设计
架构
笨鸟飞不快1 天前
从 MVC 到 DDD:一次真实的渐进式迁移实录
后端·架构
青禾网络1 天前
Web 前端如何接入 AI 音效生成:从零到可用的完整方案
人工智能·设计模式
这个DBA有点耶2 天前
GROUP BY优化全解:如何写出既不丢数据又飞快的分组查询
数据库·mysql·架构
锋行天下2 天前
我试图优化 Vite 的拆包,结果首屏慢了 10 倍
前端·vue.js·架构
ZJPRENO2 天前
吃透软件开发六大设计原则,告别烂代码
设计模式