责任链模式是一种行为型设计模式。在这种模式中,会为请求创建一条由多个Handler组成的链路。每一个进入的请求,都会经过这条链路。这条链路上的Handler可以选择如下操作:

  • 处理请求或跳过处理
  • 决定是否将请求传给这条链路上的下一个Handler

下面是责任链模式的用例图:

关于责任链模式的用途最好还是用个案例来说明下。

以医院为例。在一个医院中会有如下职责成员:

  1. 挂号处
  2. 医生
  3. 收银处
  4. 药房

当病人来医院看病时,他会先去挂号处挂号,然后找医生看病,看完病后去收银处缴费,最后去药房拿药。在这个过程中,病人需要经过一个由四个职责部门组成的链条。病人在一个职责部门的事务结束后才能进入后续的职责部门,在这个过程中我们可以清晰地看到一条职责链。

现在可以说说责任链模式的适用场景了:

  1. 当一个请求需要经过多个环节的处理时;
  2. 因为有多个对象可以处理某个请求,但我们并不想让客户端选择处理请求的对象,同时我们还想将客户端和处理器解耦,此时我们可以选择职责链模式:客户端只需要和职责链中的第一个处理器接触就可以了。

下面是病人到医院看病这个实例的类图:

实现代码如下:

department.go

type department interface {
execute(*patient)
setNext(department)
}

medical.go

import "fmt"

type medical struct {
next department
} func (m *medical) execute(p *patient) {
if p.medicineDone {
fmt.Println("Medicine already given to patient")
m.next.execute(p)
return
}
fmt.Println("Medical giving medicine to patient")
p.medicineDone = true
m.next.execute(p)
} func (m *medical) setNext(next department) {
m.next = next
}

cashier.go

import "fmt"

type cashier struct {
next department
} func (c *cashier) execute(p *patient) {
if p.paymentDone {
fmt.Println("Payment Done")
}
fmt.Println("Cashier getting money from patient patient")
c.next.execute(p)
} func (c *cashier) setNext(next department) {
c.next = next
}

doctor.go

import "fmt"

type doctor struct {
next department
} func (d *doctor) execute(p *patient) {
if p.doctorCheckUpDone {
fmt.Println("Doctor checkup already done")
d.next.execute(p)
return
}
fmt.Println("Doctor checking patient")
p.doctorCheckUpDone = true
d.next.execute(p)
} func (d *doctor) setNext(next department) {
d.next = next
}

reception.go

import "fmt"

type reception struct {
next department
} func (r *reception) execute(p *patient) {
if p.registrationDone {
fmt.Println("Patient registration already done")
r.next.execute(p)
return
}
fmt.Println("Reception registering patient")
p.registrationDone = true
r.next.execute(p)
} func (r *reception) setNext(next department) {
r.next = next
}

patient.go

type patient struct {
name string
registrationDone bool
doctorCheckUpDone bool
medicineDone bool
paymentDone bool
}

  main.go

func main() {

	medical := &medical{}

	//Set next for cashier department
cashier := &cashier{}
cashier.setNext(medical)
//Set next for doctor department
doctor := &doctor{}
doctor.setNext(cashier)
//Set next for reception department
reception := &reception{}
reception.setNext(doctor) patient := &patient{name: "abc"}
//Patient visiting
reception.execute(patient)
}

执行结果如下:

Reception registering patient
Doctor checking patient
Cashier getting money from patient patient
Medical giving medicine to patient

代码已上传至GitHub:zhyea / go-patterns / Chain of Responsibility Design Pattern

END!

GoLang设计模式07 - 责任链模式的更多相关文章

  1. 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)

    原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...

  2. php设计模式之责任链模式

    php设计模式之责任链模式 实际问题 你的论坛有举报功能,版主能解决粗口方面的举报,警察能解决严重一点的黄赌毒方面的举报,更严重的反政府的举报就需要由国安局来完成. 职场中每个人都有直属的上级,如果到 ...

  3. python设计模式之责任链模式

    python设计模式之责任链模式 开发一个应用时,多数时候我们都能预先知道哪个方法能处理某个特定请求.然而,情况并非总是如此.例如,想想任意一种广播计算机网络,例如最早的以太网实现.在广播计算机网络中 ...

  4. 【GOF23设计模式】责任链模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_责任链模式.公文审批.供应链系统的采购审批.异常链.过滤器和拦截器调用过程 package com.test.chainO ...

  5. C#设计模式:责任链模式

    设计模式是面向对象编程的基础,是用于指导程序设计.在实际项目开发过程中,并不是一味将设计模式进行套用,也不是功能设计时大量引入设计模式.应该根据具体需求和要求应用适合的设计模式.设计模式是一个老话题了 ...

  6. 详解java设计模式之责任链模式

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt175 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次 ...

  7. Head First设计模式之责任链模式

    一.定义 避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止. 主要解决:职责链上的处理者负责处理请求,客户只需要将请求 ...

  8. 【Unity与23种设计模式】责任链模式(Chain of Responsibility)

    GoF中定义: "让一群对象都有机会来处理一项请求,以减少请求发送者与接收者之间的耦合度.将所有的接受对象串联起来,让请求沿着串接传递,直到有一个对象可以处理为止." 举个现实中的 ...

  9. Java进阶篇设计模式之八 ----- 责任链模式和命令模式

    前言 在上一篇中我们学习了结构型模式的享元模式和代理模式.本篇则来学习下行为型模式的两个模式, 责任链模式(Chain of Responsibility Pattern)和命令模式(Command ...

随机推荐

  1. Easylogging++的使用及扩展

    目录 简介 使用 扩展 配置日志路径 时间滚动日志 自动删除日志 封装到一个头文件 源代码优化(不推荐) 附件 简介 Easylogging++ 是用于 C++ 应用程序的单头高效日志库.它非常强大, ...

  2. 备战秋招之十大排序——O(n)级排序算法

    时间复杂度O(n)级排序算法 九.计数排序 前文说到,19591959 年 77 月,希尔排序通过交换非相邻元素,打破了 O(n^2)的魔咒,使得排序算法的时间复杂度降到了 O(nlog n) 级,此 ...

  3. 【译】JavaScript async / await:好的部分,陷阱和如何使用

    async/await提供了一种使用同步样式代码异步访问资源的选项,而不会阻塞主线程.然而,使用它有点棘手.在本文中,我们将从不同的角度探讨async / await,并将展示如何正确有效地使用它们. ...

  4. 【springcloud alibaba】配置中心之nacos

    接着上一篇的[springcloud alibaba]注册中心之nacos,这一篇主要讲nacos的配置中心能力.nacos的集群部署及持久化请看上一篇. ---------------------- ...

  5. springboot中@Mapper和@Repository的区别

    @Mapper和@Repository是常用的两个注解,两者都是用在dao上,两者功能差不多,容易混淆,有必要清楚其细微区别: 区别: @Repository需要在Spring中配置扫描地址,然后生成 ...

  6. WPF学习笔记二 依赖属性实现原理及性能分析

    在这里讨论依赖属性实现原理,目的只是学习WPF是怎么设计依赖属性的,同时更好的使用依赖属性. 首先我们来思考一个简单的问题:我们希望能验证属性的值是否有效,属性变更时进行自己的处理.回顾一下.net的 ...

  7. 1.3RDD的设计与运行原理

    此文为个人学习笔记如需系统学习请访问http://dblab.xmu.edu.cn/blog/1709-2/ 提供一种通用的数据抽象 RDD典型的执行过程如下: RDD读入外部数据源(或者内存中的集合 ...

  8. 常用数据库JDBC

    JDBC的URL=协议名+子协议名+数据源名.1. 协议名总是"jdbc".2.子协议名由JDBC驱动程序的编写者决定.3. 数据源名也可能包含用户与口令等信息:这些信息也可单独提 ...

  9. rEFI引导Win10+Ubuntu14双系统

    公司买了一台Alienware 15 R2,安装双系统折腾死我了,现在记录一下安装过程. 硬盘: 256固态+1T机械 安装顺序: 先Windows,再Ubuntu 不同BIOS启动方式下安装系统 U ...

  10. QT如何发布应用程序和图标

    1.程序图标 ①创建一个图标格式的文件,可以网上在线将普通的图形格式转成.ico 格式的图标文件 http://www.faviconico.org/ 这个网站可以在线转换png.jpg.gif文件为 ...