14.Golang设计模式之责任链模式

ShawnLee_123 · · 1350 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

责任链模式

GitHub代码链接

1. 简介

Chain of Responsibility Pattern为请求创建一个接受者对象的链,这样可以使得请求和发送者解耦。

2. 责任链模式解决的问题

为了避免请求者和发送者耦合在一起,让多个对象都有可能接收数据,我们将这些接受者对象连城一个链,并且沿着这条链传递请求。直到有对象处理这个请求为止。

2.1 使用场景

  • js中的事件冒泡
  • Linux内核中的软件中断

2.2 优点

  • 降低耦合度
  • 简化接收对象,增加和减少请求的处理很容易
  • 通过改变链内的成员或者调动他们的顺序,可以动态新增和删除责任。

2.3 缺点

  • 不能保证请求一定被处理
  • 调试代码时不方便,不容易观察运行时的特征,排查错误不方便。

3. 责任链模式实现

我们定义三个等级的日志类,组成一条责任链。用户在打印日志时,只需要调用一个接口,然后
责任链上的日志类会依次判断是否需要打印。

3.1 日志类接口

const (
    //StandardLogLevel 标准日志等级
    StandardLogLevel = iota
    //InfoLogLevel info日志等级
    InfoLogLevel
    //ErrorLogLevel 错误日志等级
    ErrorLogLevel
)

//BaseLogger 日志接口
type BaseLogger interface {
    PrintLog(level int, message string)
    Write(message string)
}

3.2 实现3个日志类

//StandardLogger 标准日志类
type StandardLogger struct {
    Level      int
    NextLogger BaseLogger
}

//NewStandardLogger 实例化标准日志类
func NewStandardLogger() *StandardLogger {
    return &StandardLogger{
        Level:      StandardLogLevel,
        NextLogger: nil,
    }
}

//Write 标准日志类写日志方法
func (sl *StandardLogger) Write(message string) {
    fmt.Printf("Standard Logger out: %s.\n", message)
}

//PrintLog 标准日志类输入日志,并且流向下一个对象方法
func (sl *StandardLogger) PrintLog(level int, message string) {
    if sl.Level == level {
        sl.Write(message)
    }
    if sl.NextLogger != nil {
        sl.NextLogger.PrintLog(level, message)
    }
}

//SetNextLogger 标准日志类设置下一个对象方法
func (sl *StandardLogger) SetNextLogger(logger BaseLogger) {
    sl.NextLogger = logger
}

//InfoLogger 提示日志类
type InfoLogger struct {
    Level      int
    NextLogger BaseLogger
}

//NewInfoLogger 实例化提示日志类
func NewInfoLogger() *InfoLogger {
    return &InfoLogger{
        Level:      InfoLogLevel,
        NextLogger: nil,
    }
}

//Write 提示日志类的写方法
func (infoL *InfoLogger) Write(message string) {
    fmt.Printf("Info Logger out: %s.\n", message)
}

//PrintLog 提示日志类的输入日志方法
func (infoL *InfoLogger) PrintLog(level int, message string) {
    if infoL.Level == level {
        infoL.Write(message)
    }
    if infoL.NextLogger != nil {
        infoL.NextLogger.PrintLog(level, message)
    }
}

//SetNextLogger 提示日志类设置下一个对象
func (infoL *InfoLogger) SetNextLogger(logger BaseLogger) {
    infoL.NextLogger = logger
}

//ErrorLogger 错误日志类
type ErrorLogger struct {
    Level      int
    NextLogger BaseLogger
}

//NewErrorLogger 实例化错误日志类
func NewErrorLogger() *ErrorLogger {
    return &ErrorLogger{
        Level:      ErrorLogLevel,
        NextLogger: nil,
    }
}

//Write 错误日志类写方法
func (el *ErrorLogger) Write(message string) {
    fmt.Printf("Error logger out: %s.\n", message)
}

//PrintLog 错误日志类输入日志方法
func (el *ErrorLogger) PrintLog(level int, message string) {
    if el.Level == level {
        el.Write(message)
    }
    if el.NextLogger != nil {
        el.NextLogger.PrintLog(level, message)
    }
}

//SetNextLogger 错误日志类设置下一个对象
func (el *ErrorLogger) SetNextLogger(logger BaseLogger) {
    el.NextLogger = logger
}

3.3 责任链实现

//GetChainOfLoggers 获取日志对象链
func GetChainOfLoggers() BaseLogger {
    errLog := NewErrorLogger()
    infoLog := NewInfoLogger()
    standardLog := NewStandardLogger()

    errLog.SetNextLogger(infoLog)
    infoLog.SetNextLogger(standardLog)

    return errLog
}

上一篇

13.Golang设计模式之代理模式

下一篇


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:ShawnLee_123

查看原文:14.Golang设计模式之责任链模式

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1350 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传