《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()


相关推荐
xy_recording1 小时前
Day08 Go语言学习
开发语言·学习·golang
吧唧霸1 小时前
golang读写锁和互斥锁的区别
开发语言·算法·golang
Keya3 小时前
MacOS端口被占用的解决方法
前端·后端·设计模式
顾林海3 小时前
从"面条代码"到"精装别墅":Android MVPS架构的逆袭之路
android·面试·架构
就是帅我不改4 小时前
SpringBoot多租户架构设计终极指南:5种方案彻底解决企业级SaaS隔离难题
后端·面试·架构
IT小番茄4 小时前
Docker自动构建镜像全攻略:从Buildx新特性到CI/CD安全实践[六]
架构
呼啦啦小魔仙4 小时前
Elpis:基于 Koa.js 的企业级定制 Node.js 框架
架构
已读不回1434 小时前
设计模式-单例模式
前端·设计模式
Joey_Chen4 小时前
【源码赏析】开源C++日志库spdlog
架构·源码阅读