餐馆的故事-浅析职责链模式

我们在餐馆吃饭的时候,一般都是在拿到菜单后,选择喜欢的菜,然后通知服务员。服务员会将我们的定单交给大厨,大厨可能会亲自去做这道菜,也可能安排给小厨来做,总之,我们不用担心他们没有人做菜,即使有时候等的时间长点。

下面我们来分析一下。首先,对于我们这些点菜的人来说,我们一般不了解这些厨师,我们没法找到某个具体的厨师让他去做,所以只好把请求交给服务员;然后,对于餐馆的服务员、大厨、小厨来说,他们都可以接受并处理这个请求,但很明显,他们有分工,不会一人去做所有的菜。

简单地说,顾客发送请求(点菜),餐馆的人接受请求(拿到定单),有多个人可以处理该请求(做菜),或者说履行职责,但最后只有一人处理该请求。如下图所示:

CoR

这当中就包含了职责链模式(Chain Of Responsibility,简称CoR)。

我们来看看Gof中CoR的描述:

意图

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

从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转发给链中的下一个候选者,请求发送者不确定到底哪个对象会处理它,——我们称该请求有一个隐式的接受者(implicit receiver)。

在餐馆的例子中,顾客是请求的发送者,接受者则是服务员、大厨、小厨,他们构成了一条职责链,他们当中会一个人来处理请求。

好了,菜终于上来了,先把它吃掉吧...

现在走出餐馆,我们来看看在一般场景下,CoR的类图是:

CoR2

参与者

Handler(如Employee)

——定义一个处理请求的接口;

ConcreteHandler(如Server和Chef)

——处理它负责的请求;

——可访问它的后继者(Successor);

——如果可处理该请求,处理之;否则转发给后继者;

Client

——向职责链提交请求。

适用性

1、有多个的对象可以处理一个请求,而具体的处理者在运行时自动确定;

2、希望在对接受者不了解的情况下,向多个对象的一个提交请求;

3、处理请求的对象集合需要动态指定。

示例代码

using System;
 
namespace ChainOfPatterns
{
    class Program
    {
        static void Main(string[] args)
        {
            // 餐馆工作人员
            Server server = new Server("anders");
            Chef chef = new Chef("dudu");
            AssistantChef ac = new AssistantChef("bill");
            server.SetSuccessor(chef);
            chef.SetSuccessor(ac);
 
            Customer customer = new Customer();
            // 点第一道菜
            customer.OrderName = "酸辣土豆丝";
            server.HandleRequest(customer);
 
            // 点第二道菜
            customer.OrderName = "农家小炒肉";
            server.HandleRequest(customer);
 
            Console.ReadLine();
        }
    }
 
    public class Customer
    {
        private string orderName;
 
        public string OrderName
        {
            get { return orderName; }
            set { orderName = value; }
        }
    }
 
    public abstract class Employee
    {
        protected string name;
        protected Employee successor;
 
        public Employee(string name)
        {
            this.name = name;
        }
 
        public void SetSuccessor(Employee successor)
        {
            this.successor = successor;
        }
 
        public virtual void HandleRequest(Customer customer)
        {
            if (successor != null)
            {
                successor.HandleRequest(customer);
            }
        }
    }
 
    /// <summary>
    /// 服务员不用炒菜,所以直接转发给后继者。
    /// </summary>
    public class Server : Employee
    {
        public Server(string name) : base(name)
        {
        }
    }
 
    public class Chef : Employee
    {
        public Chef(string name) : base(name)
        {
        }
 
        public override void HandleRequest(Customer customer)
        {
            if (customer.OrderName == "农家小炒肉")
            {
                Console.WriteLine("{0}做的{1}", name, customer.OrderName);
            }
            else
            {
                base.HandleRequest(customer);
            }
        }
    }
 
    public class AssistantChef : Employee
    {
        public AssistantChef(string name) : base(name)
        {
        }
 
        public override void HandleRequest(Customer customer)
        {
            if (customer.OrderName == "酸辣土豆丝")
            {
                Console.WriteLine("{0}做的{1}", name, customer.OrderName);
            }
            else
            {
                base.HandleRequest(customer);
            }
        }
    }
}

注意

如果我们运气很差,点了一个没有存货的菜,那么不管是服务员还是大厨、小厨都没法处理了。也就是说,对于一个请求,可能没有任何接受者会处理它。

问题

我还想到一个问题,如果一道菜很复杂,需要大厨和小厨一起做,该怎么办呢?望各路高手指点迷津 :)

其它的例子

浏览器事件模型

假设我们的HTML页面上有一个<div />,它又包含了一个<input />按钮,对于按钮的click事件来说,在IE中它的触发顺序为从最特定的事件目标(button)道最不特定的事件目标(document对象)。input,div,body到document,它们也构成了一条职责链。

击鼓传花

击鼓传花是一种热闹而又紧张的饮酒游戏。在酒宴上宾客依次坐定位置,由一人击鼓,击鼓的地方与传花的地方是分开的,以示公正。开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在某人手中,则该人就得饮酒。

看起来,酒宴上的宾客构成了一条链。但我认为这是CoR的一个反面例子。对于每一轮具体的游戏来说,这些宾客唯一能做的事情就是将花束传递(转发给后继者),没有谁能够主动停下来,而能够处理请求的人(击鼓者)到底是谁的后继者呢?这个并不确定,职责链如何构建呢?

另外,建议看一看下面两篇文章中高手的论述:职责链模式在开发中的应用,手拉手就是职责链吗?

 

参考:

《设计模式-可复用面向对象软件的基础》 Gof

《UML基础、案例与应用》Joseph Schmuller

http://www.dofactory.com/Patterns/PatternChain.aspx


本文转自一个程序员的自省博客园博客,原文链接:http://www.cnblogs.com/anderslly/archive/2008/02/28/chainOfResponsibility.html,如需转载请自行联系原作者。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/453436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab非齐次方程组的通解,用matlab求非齐次线性方程组的通解?

先向大家介绍一下非齐次线性方程组。所谓非齐次线性方程组就是方程组等号右边的常数项不全为零的线性方程组。全部等于零时&#xff0c;就称为齐次线性方程组。下面我们就讲解一下如何利用matlab快速求非齐次线性方程组的通解。工具/材料matlab电脑操作方法01线性方程组Axb的求…

Linux 终端仿真程序Putty

PuTTY是一个Telnet、SSH、rlogin、纯TCP以及串行接口连接软件。较早的版本仅支持Windows平台&#xff0c;现在的版本中开始支持各类Unix平台。 用linux作为桌面系统&#xff0c;身为工程师很多时候需要通过Telnet、SSH协议进行远程管理&#xff0c;通过串口进行设备配置。Putty…

粗识静态链表

为了弥补链表在内存分配上的不足&#xff0c;出现了静态链表这么一个折中的办法。静态链表比较类似于内存池&#xff0c;它会预先分配一个足够长的数组&#xff0c;之后链表节点都会保存在这个数组里&#xff0c;这样就不需要频繁的进行内存分配了。 当然&#xff0c;这个方法的…

php用date语句获取时间,关于php date()函数获取时间的设置和使用方法

date()函数是PHP自带的时间函数&#xff0c;可以获取当前服务器的时间echo date(Y-m-d H:i:s); //输出:2020-05-18 11:02:35date()函数中可以使用的字母含义&#xff1a;a-"am"(上午)或者"pm"(下午)A-"AM"或者"PM"Y-年&#xff0c;显示…

Django_form补充

问题1: 注册页面输入为空&#xff0c;报错&#xff1a;keyError&#xff1a;找不到passworddef clean(self): print("---",self.cleaned_data) # if self.cleaned_data["password"]self.cleaned_data["repeat_password"]: …

WF4.0:NativeActivity中的错误处理

备注&#xff1a;这篇文章的使用环境是.NET framework 4.0 RC 1 在WF4中创建native活动时&#xff0c;NativeActivity是非常强大的。其众多的功能之一是围绕错误处理。 调度子活动的时的基本错误处理。 当NativeActivity执行的时候&#xff0c;它是通过一个NativeActivityConte…

Cadence 电源完整性仿真实践(二)

转载于:http://blog.csdn.net/wu20093346/article/details/38050917 通过以上步骤对每个平面进行了单节点分析并观测了响应曲线&#xff0c;接下来将观测平面对的目标阻抗是否满足要求&#xff0c;通过选择电容器的方法来减小含有电容器阻抗响应曲线中的反谐振波峰。在SigWave窗…

Johnson 全源最短路径算法

解决单源最短路径问题&#xff08;Single Source Shortest Paths Problem&#xff09;的算法包括&#xff1a; Dijkstra 单源最短路径算法&#xff1a;时间复杂度为 O(E VlogV)&#xff0c;要求权值非负&#xff1b; Bellman-Ford 单源最短路径算法&#xff1a;时间复杂度为 O…

Machine Learning 学习笔记1 - 基本概念以及各分类

What is machine learning? 并没有广泛认可的定义来准确定义机器学习。以下定义均为译文&#xff0c;若以后有时间&#xff0c;将补充原英文...... 定义1、来自Arthur Samuel&#xff08;上世纪50年代、西洋棋程序&#xff09; 在进行特定编程的情况下给予计算机学习能力的领域…

蒙特 卡罗方法matlab,蒙特·卡罗方法中的数学之美,你一定不想错过

原标题&#xff1a;蒙特卡罗方法中的数学之美&#xff0c;你一定不想错过有方教育——我们致力于为中学生提供学界和业界前沿的学术科研教育内容&#xff0c;帮助学生参加海外科研项目&#xff0c;在提升申请竞争力的同时&#xff0c;获得领跑优势。一、概述蒙特卡罗方法(Monte…

【 CDN 最佳实践】CDN 命中率优化思路

CDN 在静态资源的加速场景中是将静态资源缓存在距离客户端较近的CDN 节点上&#xff0c;然后客户端访问该资源即可通过较短的链路直接从缓存中获取资源&#xff0c;而避免再通过较长的链路回源获取静态资源。因此 CDN的缓存命中率的高低直接影响客户体验&#xff0c;而保证较高…

Python基础-time and datetime

一、在Python中&#xff0c;通常有这几种方式来表示时间&#xff1a; 时间戳格式化的时间字符串元组&#xff08;struct_time&#xff09;共九个元素。由于Python的time模块实现主要调用C库&#xff0c;所以各个平台可能有所不同。1.时间戳&#xff08;timestamp&#xff09;的…

matlab中欧姆如何表示,在excel中欧姆符号怎么打

在excel中欧姆符号怎么打&#xff0c;相信对于好多熟练用excel的朋友来说&#xff0c;是很简单不过的&#xff0c;但是对于有些初学者来说&#xff0c;就是菜鸟啦&#xff0c;就有点懵懵懂懂的感觉了&#xff0c;毕竟刚接触的东西还没用过嘛。但是&#xff0c;没关系今天笔者就…

zookeeper伪集群(在一台机器上集群)

2019独角兽企业重金招聘Python工程师标准>>> 创建一下的目录结构zookeeper-3.4.10是你下载的zookeeper的解压包 /zookeeper_cluster----/server_one|---/data|myid(文件)|---/datalog|---/zookeeper-3.4.10|---/bin|---/conf|---zoo.cfg|---..... |---/....----/ser…

Spring核心接口之Ordered

一、Ordered接口介绍Spring中提供了一个Ordered接口。从单词意思就知道Ordered接口的作用就是用来排序的。Spring框架是一个大量使用策略设计模式的框架&#xff0c;这意味着有很多相同接口的实现类&#xff0c;那么必定会有优先级的问题。于是Spring就提供了Ordered这个接口&a…

将本地代码上传至github

注册github账号 https://github.com/ 安装git工具 https://git-for-windows.github.io 1.在github中创建一个项目 2.填写相应信息&#xff0c;点击create Repository name: 仓库名称 Description(可选): 仓库描述介绍 Public, Private : 仓库权限&#xff08;公开共享&#xff…

Java二十三设计模式之------工厂方法模式

一、工厂方法模式&#xff08;Factory Method&#xff09; 工厂方法模式有三种 1、普通工厂模式&#xff1a;就是建立一个工厂类&#xff0c;对实现了同一接口的一些类进行实例的创建。首先看下关系图&#xff1a; 举例如下&#xff1a;&#xff08;我们举一个发送邮件和短信的…

一元多项式乘法算法

我认为大致算法应该是这样的: 首先准备一个空的链表L。利用第一个多项式的的指针所指的节点数值乘以多项式二的每一项&#xff0c;将结果保存在链表L中。 然后将指向该节点的指针后移到下一个节点继续进行乘法运算&#xff0c;将所得结果加到L中&#xff08;这个操作已经在一…

Oracle 基础

为什么80%的码农都做不了架构师&#xff1f;>>> Oracle DB笔录&#xff0c;以后会不断Add&#xff0c;欢迎留言补充! --cmd.exe(你懂得!) --[1]多个数据库实例&#xff0c;切换选择DB后&#xff0c;登录操作 set ORACLE_SIDorcl --选择DB orcl(你的DB实例名) --可在…

Linux执行命令提示Password,linux expect远程自动登录以及执行命令

linux远程自动登录以及执行命令远程登录该自动登录的过程是通过shell里面expect实现的&#xff0c;类似相当于开了一个类似于cmd的命令段输出IP和密码。注意该脚本能够执行的前提是安装了expectyum install -y expect直接上脚本&#xff1a;#!/usr/bin/expect …