【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)

}
相关推荐
离陌在学C#1 小时前
C# 事件(Event)详解:从概念到实战
开发语言·c#
Terra.K1 小时前
Java异常学习[特殊字符]
java·开发语言·学习
葡萄城技术团队3 小时前
InfluxDB 2\.x 深度解析:核心架构、Flux 函数与制造业落地指南(三)
java·开发语言·架构
counting money3 小时前
Java IO流详解:从InputStream到文件操作实战
java·开发语言·python
wuyk5553 小时前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
峥无4 小时前
从0到1手撕红黑树:封装实现 my_map 与 my_set(SGI-STL 源码级深度解析)
开发语言·c++·笔记·算法·stl
波特率1152004 小时前
C++新特性---属性说明符与标准属性
开发语言·c++
程序员小八7774 小时前
上海百度B端java后端日常实习一面
java·开发语言
wp123_14 小时前
IPX8 防水 Type‑C连接器:安费诺 124018792112A 与 TONEVEE TY48087‑24A 技术梳理
c语言·开发语言
不会代码的小猴4 小时前
3. 控件学习1
开发语言·c++·笔记·qt·算法