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

}
相关推荐
噢,我明白了4 小时前
JAVA中的一些基础应用知识点
java·开发语言
时间的拾荒人5 小时前
Redis 入门详解:核心特性、重要文件与全局命令实战
开发语言·redis·面试
敲上瘾5 小时前
Qt Widgets入门:项目模板解析与Hello World
开发语言·数据库·c++·qt·ui·qt6.3
码途行者6 小时前
网站的SQL 注入:从攻击原理到防御措施
开发语言·sql·php
利威尔xu6 小时前
Go map 底层崩溃:3 个 goroutine 并发写同一张 map,fatal error 崩掉整个服务
golang·源码·map·并发·后端开发
旖旎夜光7 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习
你看我名字7 小时前
产品参数昨天还对,今天已过期:数眼智能与大模型应用如何做资料版本校验
开发语言·架构
老秦包你会8 小时前
计算机网络第二课 ----Socket(套接字)编程预备
开发语言·计算机网络·php
旖旎夜光8 小时前
【C++ 基础入门】C++多态(下):单/多继承虚表、多态补充与 21 道高频题
开发语言·c++·笔记·学习
Wang's Blog17 小时前
Java 项目实战: 交友项目 - FastDFS:入门案例
java·开发语言·交友