Go和Java实现责任链模式

Go和Java实现责任链模式

下面通过一个审批流程的案例来说明责任链模式的使用。

1、责任链模式

责任链模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这

种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的

请求传给下一个接收者,依此类推。

  • 意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且

    沿着这条链传递请求,直到有对象处理它为止。

  • 主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细

    节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

  • 何时使用:在处理消息的时候以过滤很多道。

  • 如何解决:拦截的类都实现统一接口。

  • 关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向

    谁传递之前 set 进去。

  • 应用实例:1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding

    的处理,Struts2 的拦截器,jsp servlet 的 Filter。

  • 优点:1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。

    3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责

    任。 4、增加新的请求处理类很方便。

  • 缺点:1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能

    会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。

  • 使用场景:1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明

    确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。

  • 注意事项:在 JAVA WEB 中遇到很多应用。

  • 适用性:

    有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。

    你在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

    可处理一个请求的对象集合应被动态指定。

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一个链,并随着

这条链传递该请求,直到有一个对象处理它为止。这一模式的想法是,给多个对象处理一个请求的机会,从而解耦

发送者和接受者。

2、Go实现责任链模式1

go 复制代码
package chainofresponsibility

// ========== 定义一个处理请求的接口Request ==========
type Request interface {
	Processing()
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== 离职DimissionRequest ==========
type DimissionRequest struct {
}

func (dimissionRequest *DimissionRequest) Processing() {
	fmt.Println("处理离职!")
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== 请假LeaveRequest ==========
type LeaveRequest struct {
}

func (LeaveRequest *LeaveRequest) Processing() {
	fmt.Println("处理请假!")
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== 加薪AddMoneyRequest ==========
type AddMoneyRequest struct {
}

func (addMoneyRequest *AddMoneyRequest) Processing() {
	fmt.Println("处理加薪!")
}
go 复制代码
package chainofresponsibility

// 处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理请求,否则将该请求转发给它的后继者
// ========== RequestHandle ==========
type RequestHandle interface {
	HandleRequests(Request)
	Next(RequestHandle)
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== HRRequestHandle ==========
type HRRequestHandle struct {
	requestHandle RequestHandle
}

func (hRRequestHandle *HRRequestHandle) HandleRequests(request Request) {
	if req, ok := request.(*DimissionRequest); ok {
		fmt.Println("要离职,人事审批!")
		req.Processing()
	}
	fmt.Println("请求完成!")
}

func (hRRequestHandle *HRRequestHandle) Next(requestHandle RequestHandle) {
	hRRequestHandle.requestHandle = requestHandle
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== PMRequestHandle ==========
type PMRequestHandle struct {
	requestHandle RequestHandle
}

func (pMRequestHandle *PMRequestHandle) HandleRequests(request Request) {
	if req, ok := request.(*AddMoneyRequest); ok {
		fmt.Println("要加薪,项目经理审批!")
		req.Processing()
	} else {
		pMRequestHandle.requestHandle.HandleRequests(request)
	}
}

func (pMRequestHandle *PMRequestHandle) Next(requestHandle RequestHandle) {
	pMRequestHandle.requestHandle = requestHandle
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== TLRequestHandle ==========
type TLRequestHandle struct {
	requestHandle RequestHandle
}

func (tLRequestHandle *TLRequestHandle) HandleRequests(request Request) {
	if req, ok := request.(*LeaveRequest); ok {
		fmt.Println("要请假,项目组长审批!")
		req.Processing()
	} else {
		tLRequestHandle.requestHandle.HandleRequests(request)
	}
}

func (tLRequestHandle *TLRequestHandle) Next(requestHandle RequestHandle) {
	tLRequestHandle.requestHandle = requestHandle
}
go 复制代码
package main

import (
	"fmt"
	. "proj/chainofresponsibility"
)

func main() {
	hr := HRRequestHandle{}
	pm := PMRequestHandle{}
	tl := TLRequestHandle{}

	tl.Next(&pm)
	pm.Next(&hr)

	fmt.Println("===========")
	// 人事处理离职请求
	tl.HandleRequests(&DimissionRequest{})

	fmt.Println("===========")
	// 项目经理处理加薪请求
	tl.HandleRequests(&AddMoneyRequest{})

	fmt.Println("========")
	// 组长处理请假请求
	tl.HandleRequests(&LeaveRequest{})
}
shell 复制代码
# 程序输出
===========
要离职,人事审批!
处理离职!
请求完成!
===========
要加薪,项目经理审批!
处理加薪!
========
要请假,项目组长审批!

3、Java实现责任链模式1

java 复制代码
package com.chainofresponsibility;

// ========== 定义一个处理请求的接口Request ==========
public interface Request {
    void processing();
}
java 复制代码
package com.chainofresponsibility;

// ========== 请假LeaveRequest ==========
public class LeaveRequest implements Request{
    @Override
    public void processing() {
        System.out.println("处理请假!");
    }
}
java 复制代码
package com.chainofresponsibility;

// ========== 加薪AddMoneyRequest ==========
public class AddMoneyRequest implements Request {
    @Override
    public void processing() {
        System.out.println("处理加薪!");
    }
}
java 复制代码
package com.chainofresponsibility;

// ========== 离职DimissionRequest ==========
public class DimissionRequest implements Request{
    @Override
    public void processing() {
        System.out.println("处理离职!");
    }
}
java 复制代码
package com.chainofresponsibility;

// 处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理请求,否则将该请求转发给它的后继者
// ========== RequestHandle ==========
public abstract class RequestHandle {
    RequestHandle requestHandle;
    abstract void handleRequest(Request request);
    void next(RequestHandle requestHandle){
        this.requestHandle = requestHandle;
    }
}
java 复制代码
package com.chainofresponsibility;

// ========== HRRequestHandle ==========
public class HRRequestHandle extends RequestHandle {

    @Override
    public void handleRequest(Request request) {
        if (request instanceof DimissionRequest) {
            System.out.println("要离职,人事审批!");
            request.processing();
        }
        System.out.println("请求完成");
    }
}
java 复制代码
package com.chainofresponsibility;

// ========== PMRequestHandle ==========
public class PMRequestHandle extends RequestHandle {

    @Override
    public void handleRequest(Request request) {
        if (request instanceof AddMoneyRequest) {
            System.out.println("要加薪,项目经理审批!");
            request.processing();
        } else {
            requestHandle.handleRequest(request);
        }
    }
}
java 复制代码
package com.chainofresponsibility;

public class TLRequestHandle extends RequestHandle {

    @Override
    public void handleRequest(Request request) {
        if (request instanceof LeaveRequest) {
            System.out.println("要请假,项目组长审批!");
            request.processing();
        } else {
            requestHandle.handleRequest(request);
        }
    }
}
java 复制代码
package com.chainofresponsibility;

public class Test {

    public static void main(String[] args) {

        RequestHandle hr = new HRRequestHandle();
        RequestHandle pm = new PMRequestHandle();
        RequestHandle tl = new TLRequestHandle();

        tl.next(pm);
        pm.next(hr);

        System.out.println("===========");
        // 人事处理离职请求
        Request request = new DimissionRequest();
        tl.handleRequest(request);

        System.out.println("===========");
        // 项目经理处理加薪请求
        request = new AddMoneyRequest();
        tl.handleRequest(request);

        System.out.println("========");
        // 组长处理请假请求
        request = new LeaveRequest();
        tl.handleRequest(request);
    }
}
shell 复制代码
# 程序输出
===========
要离职,人事审批!
处理离职!
请求完成
===========
要加薪,项目经理审批!
处理加薪!
========
要请假,项目组长审批!
处理请假!

4、Go实现责任链模式2

创建 AbstractLogger,带有详细的日志记录级别,然后我们创建三种类型的记录器,都扩展了AbstractLogger。

每个记录器消息的级别是否属于自己的级别,如果是则相应打印出来,否则将消息传递给下一个记录器。

go 复制代码
package chainofresponsibility

// ========== Logger ==========
type Logger interface {
	LogMessage(level int, message string, logger Logger)
	Write(message string)
}
go 复制代码
package chainofresponsibility

// ========== AbstractLogger ==========
type AbstractLogger struct {
	Level      int
	NextLogger Logger
}

func (s *AbstractLogger) Write(message string) {
}

func (s *AbstractLogger) LogMessage(level int, message string, logger Logger) {
	if s.Level <= level {
		logger.Write(message)
	} else {
		if s.NextLogger != nil {
			s.NextLogger.LogMessage(level, message, s.NextLogger)
		}
	}
}

func (s *AbstractLogger) SetNextLogger(logger Logger) {
	s.NextLogger = logger
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== FileLogger ==========
type FileLogger struct {
	AbstractLogger AbstractLogger
}

func (f *FileLogger) Write(message string) {
	fmt.Println("File::Logger: " + message)
}

func (f *FileLogger) LogMessage(level int, message string, logger Logger) {
	f.AbstractLogger.LogMessage(level, message, f)
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== ConsoleLogger ==========
type ConsoleLogger struct {
	AbstractLogger
}

func (c *ConsoleLogger) Write(message string) {
	fmt.Println("Standard Console::Logger: " + message)
}

func (c *ConsoleLogger) LogMessage(level int, message string, logger Logger) {
	c.AbstractLogger.LogMessage(level, message, c)
}
go 复制代码
package chainofresponsibility

import "fmt"

// ========== ErrorLogger ==========
type ErrorLogger struct {
	AbstractLogger AbstractLogger
}

func (e *ErrorLogger) Write(message string) {
	fmt.Println("Error Console::Logger: " + message)
}

func (e *ErrorLogger) LogMessage(level int, message string, logger Logger) {
	e.AbstractLogger.LogMessage(level, message, e)
}
go 复制代码
package constant

const (
	DEBUG = iota + 1
	INFO
	ERROR
)
go 复制代码
package main

import (
	. "proj/chainofresponsibility"
	. "proj/constant"
)

func main() {

	fileLogger := new(FileLogger)
	fileLogger.AbstractLogger.Level = DEBUG

	consoleLogger := new(ConsoleLogger)
	consoleLogger.AbstractLogger.Level = INFO

	errorLogger := new(ErrorLogger)
	errorLogger.AbstractLogger.Level = ERROR

	errorLogger.AbstractLogger.SetNextLogger(consoleLogger)
	consoleLogger.AbstractLogger.SetNextLogger(fileLogger)

	errorLogger.LogMessage(DEBUG, "This is a debug level information.", nil)
	errorLogger.LogMessage(INFO, "This is an info level information.", nil)
	errorLogger.LogMessage(ERROR, "This is an error level information.", nil)

}
shell 复制代码
# 程序输出
File::Logger: This is a debug level information.
Standard Console::Logger: This is an info level information.
Error Console::Logger: This is an error level information.

5、Java实现责任链模式2

java 复制代码
package com.chainofresponsibility;

// ========== AbstractLogger ==========
public abstract class AbstractLogger {

    protected int level;

    // 责任链中的下一个元素
    protected AbstractLogger nextLogger;

    public void setLevel(int level) {
        this.level = level;
    }

    public void setNextLogger(AbstractLogger nextLogger) {
        this.nextLogger = nextLogger;
    }

    public void logMessage(int level, String message) {
        if (this.level <= level) {
            write(message);
        }else{
           if(nextLogger != null) {
               nextLogger.logMessage(level, message);
           }
        }
    }

    abstract protected void write(String message);
}
java 复制代码
package com.chainofresponsibility;

// ========== FileLogger ==========
public class FileLogger extends AbstractLogger {

    @Override
    protected void write(String message) {
        System.out.println("File::Logger: " + message);
    }
}
java 复制代码
package com.chainofresponsibility;

// ========== ConsoleLogger ==========
public class ConsoleLogger extends AbstractLogger {

    @Override
    protected void write(String message) {
        System.out.println("Standard Console::Logger: " + message);
    }
}
java 复制代码
package com.chainofresponsibility;

// ========== ErrorLogger ==========
public class ErrorLogger extends AbstractLogger {

    @Override
    protected void write(String message) {
        System.out.println("Error Console::Logger: " + message);
    }
}
java 复制代码
package com.chainofresponsibility;

public class Constant {
    public static int DEBUG = 1;
    public static int INFO = 2;
    public static int ERROR = 3;
}
java 复制代码
package com.chainofresponsibility;

public class Test {

    public static void main(String[] args) {

        AbstractLogger fileLogger = new FileLogger();
        fileLogger.setLevel(Constant.DEBUG);

        AbstractLogger consoleLogger = new ConsoleLogger();
        consoleLogger.setLevel(Constant.INFO);

        AbstractLogger errorLogger = new ErrorLogger();
        errorLogger.setLevel(Constant.ERROR);

        errorLogger.setNextLogger(consoleLogger);
        consoleLogger.setNextLogger(fileLogger);

        errorLogger.logMessage(Constant.DEBUG, "This is a debug level information.");
        errorLogger.logMessage(Constant.INFO, "This is an info level information.");
        errorLogger.logMessage(Constant.ERROR, "This is an error level information.");
    }
}
shell 复制代码
# 程序输出
File::Logger: This is a debug level information.
Standard Console::Logger: This is an info level information.
Error Console::Logger: This is an error level information.
相关推荐
num_killer7 小时前
小白的Langchain学习
java·python·学习·langchain
期待のcode8 小时前
Java虚拟机的运行模式
java·开发语言·jvm
程序员老徐8 小时前
Tomcat源码分析三(Tomcat请求源码分析)
java·tomcat
a程序小傲8 小时前
京东Java面试被问:动态规划的状态压缩和优化技巧
java·开发语言·mysql·算法·adb·postgresql·深度优先
仙俊红8 小时前
spring的IoC(控制反转)面试题
java·后端·spring
阿湯哥8 小时前
AgentScope Java 集成 Spring AI Alibaba Workflow 完整指南
java·人工智能·spring
小楼v8 小时前
说说常见的限流算法及如何使用Redisson实现多机限流
java·后端·redisson·限流算法
与遨游于天地9 小时前
NIO的三个组件解决三个问题
java·后端·nio
czlczl200209259 小时前
Guava Cache 原理与实战
java·后端·spring
yangminlei9 小时前
Spring 事务探秘:核心机制与应用场景解析
java·spring boot