【go每日一题】 责任链模式的实现

责任链模式基本概念

责任链模式:Chain of Responsibility Patten 。就是将链中的每一个结点看做是一个对象,每个结点处理请求均不同,且内部自动维护一个下一个结点对象。当请求从链条的首端出发时,会沿着链的路径依次传递给每一个结点的对象,直到有对象处理这个请求为止。

就是说每个结点会处理一件事情,如果结点间出现异常,那么链路就会中断。

实现一个责任链模式

go 复制代码
package test

import (
	"errors"
	"fmt"
	"testing"
	"time"
)

// 来一个请求,携带对应的权重
// 根据权重,一级一级地走责任链

type Request struct {
	ID     int
	Weight int
	MSG    string
}

// 公共的抽象节点
type Handler interface {
	Handle(request *Request) error
	NextNode(node Handler)
}

// 节点1: mt 节点
type MTHandler struct {
	next Handler
	//suspend bool
}

func (mt *MTHandler) Handle(request *Request) error {
	if request.Weight > 0 && request.Weight < 10 {
		// 向mt发送一个审批,这里可以用channel阻塞mt的审批
		fmt.Printf("mt handler is processing req: %d\n", request.ID)
		// 如果出现异常,整个流程结束
	} else if mt.next != nil {
		mt.next.Handle(request)
	} else {
		fmt.Println("无节点可处理")
		return errors.New("无可处理节点")
	}
	return nil
}

func (mt *MTHandler) NextNode(node Handler) {
	mt.next = node
}

// 节点2: ld 节点
type LDHandler struct {
	next    Handler
	suspend bool
}

func (ld *LDHandler) Handle(request *Request) error {
	if request.Weight >= 10 && request.Weight < 30 {
		// 向mt发送一个审批消息,这里可以用channel阻塞mt的审批
		// 也可以使用数据库,这里卡着隔一段时间扫描数据库,查看审批状态
		fmt.Printf("ld handler is processing req: %d\n", request.ID)
		// 如果出现异常,整个流程结束

	} else if ld.next != nil {
		ld.next.Handle(request)
	} else {
		return errors.New("该权重无节点可以处理")
	}
	return nil

}

func (ld *LDHandler) NextNode(node Handler) {
	ld.next = node
}

func TestResponsible(t *testing.T) {

	req1 := &Request{
		ID:     1,
		Weight: 4,
		MSG:    "leave 4 days",
	}
	req2 := &Request{
		ID:     2,
		Weight: 20,
		MSG:    "leave 20 days",
	}

	reqCh := make(chan *Request, 10)
	reqCh <- req1
	reqCh <- req2

	go func(reqCh chan *Request) {
		mt := new(MTHandler)
		ld := new(LDHandler)
		mt.NextNode(ld)
		for {
			select {
			case req := <-reqCh:
				mt.Handle(req)
			}
		}

	}(reqCh)

	time.Sleep(time.Second * 3)

}
相关推荐
军训猫猫头5 分钟前
1.如何对多个控件进行高效的绑定 C#例子 WPF例子
开发语言·算法·c#·.net
真的想上岸啊19 分钟前
学习C++、QT---18(C++ 记事本项目的stylesheet)
开发语言·c++·学习
明天好,会的25 分钟前
跨平台ZeroMQ:在Rust中使用zmq库的完整指南
开发语言·后端·rust
丁劲犇1 小时前
用 Turbo Vision 2 为 Qt 6 控制台应用创建 TUI 字符 MainFrame
开发语言·c++·qt·tui·字符界面·curse
旷世奇才李先生1 小时前
Next.js 安装使用教程
开发语言·javascript·ecmascript
charlie1145141912 小时前
深入理解Qt的SetWindowsFlags函数
开发语言·c++·qt·原理分析
likeGhee3 小时前
python缓存装饰器实现方案
开发语言·python·缓存
whoarethenext3 小时前
使用 C++/Faiss 加速海量 MFCC 特征的相似性搜索
开发语言·c++·faiss
项目題供诗3 小时前
黑马python(二十五)
开发语言·python
慌糖3 小时前
RabbitMQ:消息队列的轻量级王者
开发语言·javascript·ecmascript