C#设计模式之职责链
Iron之职责链
需求:
"Iron"的建造一直没有停止,现在单个部件是有的,但是在部件从工厂里出来的时候,在组装到一起之前,我们还是非常有必要对部件进行质量检测,或者是其它个方面的检测,又或者是设置部件标识信息等等,这些操作可以是有序的(也可以是无序的)。
现在为了实现上面的所讲的功能来进行演示,然过程中会发现问题,然后解决问题。这里不多说了直接进入主题。
问题的发现:
首先我定义了一个ComponentModel类,它是要被检验的对象
- /// <summary>
- /// 部件
- /// </summary>
- public class ComponentModel
- {
- public string Name { get; set; }
- public int Value
- {
- get
- {
- return ;
- }
- }
- }
这里先定义了一个请求处理类型的枚举,下面要用到,这样比用什么字符串或者是数字来作条件判断要好很多。
- /// <summary>
- /// 请求的处理类型
- /// </summary>
- public enum RequestState
- {
- /// <summary>
- /// 检测
- /// </summary>
- Check,
- /// <summary>
- /// 设置基础值
- /// </summary>
- SetDefValue
- }
再然后,我们再来定义检验ComponentModel类的类型:
- /// <summary>
- /// 处理请求类1
- /// </summary>
- public class ConcreteHandlerCaseOne
- {
- private ComponentModel _comModel;
- public ConcreteHandlerCaseOne(ComponentModel comModel)
- {
- _comModel = comModel;
- }
- public void HandleRequest(RequestState reqState)
- {
- switch (reqState)
- {
- case RequestState.Check:
- if (_comModel.Value > )
- {
- //执行处理
- }
- break;
- case RequestState.SetDefValue:
- _comModel.Name = "默认部件";
- //执行处理
- break;
- default:
- break;
- }
- }
- }
- /// <summary>
- /// 处理请求类2
- /// </summary>
- public class ConcreteHandlerCaseTwo
- {
- private ComponentModel _comModel;
- public ConcreteHandlerCaseTwo(ComponentModel comModel)
- {
- _comModel = comModel;
- }
- public void HandleRequest(RequestState reqState)
- {
- switch (reqState)
- {
- case RequestState.Check:
- if (_comModel.Value > )
- {
- //执行处理
- }
- break;
- case RequestState.SetDefValue:
- _comModel.Name = "默认部件";
- //执行处理
- break;
- default:
- break;
- }
- }
- }
定义了两个类型,ConcreteHandlerCaseOne和ConcreteHandlerCaseTwo两个类型,都是用来处理检测ComponentModel类型的,现在这些类型都齐全了我们来检测一下吧。
- ComponentModel comModel = new ComponentModel();
- ConcreteHandlerCaseOne caseone = new ConcreteHandlerCaseOn(comModel);
- caseone.HandleRequest(RequestState.Check);
- ConcreteHandlerCaseTwo casetwo = new ConcreteHandlerCaseTw(comModel);
- casetwo.HandleRequest(RequestState.Check);
对的,就是这样,一次次的检测下去,如果要检测20次,并且都是不同的实现,那将非常可怕,代码冗余,而且请求调用方和处理方的耦合度也很大,那要怎么样让代码更精简,并且还能有效的解耦,这里就要用到职责链模式。
为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
——Gof
这里要强调一下的是本篇的示例中并没有完全遵从设计模式的定义,还是按照本文开始的功能需求来做的设计,当然了模式的核心不变。
设计模式的思想:
现在先对处理方进行抽象:
- /// <summary>
- /// 抽象处理者
- /// </summary>
- public abstract class Handle
- {
- protected Handle Successor;
- public void SetSuccessor(Handle successor)
- {
- this.Successor = successor;
- }
- public abstract void HandleRequest(RequestStatereqState,ComponentModel comModel);
- }
既然有了抽象,那就得有具体的实现:
- /// <summary>
- /// 具体处理者
- /// </summary>
- public class ConcreteHandlerA : Handle
- {
- public override void HandleRequest(RequestState reqState, ComponentModel comModel)
- {
- switch (reqState)
- {
- case RequestState.Check:
- //执行处理
- break;
- case RequestState.SetDefValue:
- //执行处理
- break;
- default:
- this.Successor.HandleRequest(reqState, comModel);
- break;
- }
- }
- }
- /// <summary>
- /// 具体处理者
- /// </summary>
- public class ConcreteHandlerB : Handle
- {
- public override void HandleRequest(RequestState reqState, ComponentModel comModel)
- {
- switch (reqState)
- {
- case RequestState.Check:
- //执行处理
- break;
- case RequestState.SetDefValue:
- //执行处理
- break;
- default:
- this.Successor.HandleRequest(reqState, comModel);
- break;
- }
- }
- }
这里的类型应该只定义一个的是为了让大家看的更明白。
在这里看抽象处理者Handle类型,它里面有个protected级别的变量Successor,Successor呢就代表着链表中每一环的指针,指向谁呢?当然是指向下一个处理者。
现在来看一下调用的代码:
- ComponentModel comModel = new ComponentModel();
- Handle handlerA = new ConcreteHandlerA();
- Handle handlerB = new ConcreteHandlerB();
- handlerA.SetSuccessor(handlerB);
- handlerA.HandleRequest(RequestState.Check, comModel);
看上去已经不错了,耦合度还是很大的,对于handlerA的调用,还是再调用方直接调用的,这时需要一个中间层,
看一下中间层的定义:
- /// <summary>
- /// ChainOfResponsibility模式帮助类
- /// </summary>
- public class CORUnit
- {
- private Handle _Handle;
- private ComponentModel _ComModel;
- public CORUnit(ComponentModel commodel)
- : this(null, commodel)
- {
- _ComModel = commodel;
- }
- public CORUnit(Handle Handle, ComponentModel commodel)
- {
- _Handle = Handle;
- _ComModel = commodel;
- }
- public void RegisterHandle(Handle handle)
- {
- if (_Handle != null)
- {
- _Handle.SetSuccessor(handle);//指向 处理链中的下一个 处理模块
- }
- else
- {
- _Handle = handle;
- }
- }
- public void HandleRequest(RequestState reqState)
- {
- _Handle.HandleRequest(reqState, _ComModel);
- }
- }
通过加了一层,再来看一下调用方的代码:
- ComponentModel comModel = new ComponentModel();
- CORUnit corunit = new CORUnit(comModel);
- corunit.RegisterHandle(new ConcreteHandlerA());
- corunit.RegisterHandle(new ConcreteHandlerB());
- corunit.HandleRequest(RequestState.Check);
- //执行处理
- //comModel的一些处理
是不是感觉调用方,跟实际的处理方之间的关系变得很弱了,这样目的也就达到了。
C#设计模式之职责链的更多相关文章
- php设计模式之职责链模式
<?php /** * @desc php设计模式之职责链模式(责任链模式) 定义:顾名思义,责任链模式为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这 ...
- 设计模式之职责链模式(JAVA实现)
学习netty框架时,看到有人说netty用到了设计模式的职责链模式,学习一下职责链模式,主要参考大话设计模式. 主要场景: 小菜想要加薪,向经理提出加薪请求,经理没有权限,经理交由总监处理,总监也没 ...
- 设计模式-利用职责链模式消除if
本文是对职责链设计模式的应用(变种),所以假设读者已经掌握了职责链设计模式,职责链模式只会应景简介. 本文主要内容: 需求(ShitCode) 职责链模式简介 设计理念 代码演示(消除if) 应用总结 ...
- 设计模式:职责链模式(Chain Of Responsibility)
定 义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止. 结构图: 处理请求类: //抽象处理类 abs ...
- 设计模式之职责链模式(Chain of Responsibility)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- TypeScript设计模式之职责链、状态
看看用TypeScript怎样实现常见的设计模式,顺便复习一下. 学模式最重要的不是记UML,而是知道什么模式可以解决什么样的问题,在做项目时碰到问题可以想到用哪个模式可以解决,UML忘了可以查,思想 ...
- Java设计模式之职责链设计模式
1.什么是-职责链设计模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求 ...
- 深入理解JavaScript系列(38):设计模式之职责链模式
介绍 职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象 ...
- php实现设计模式之 职责链模式
<?php /** * 职责链模式 * * 为解除请求的发送者和接收者之间的耦合,而使用多个对象都用机会处理这个请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它 * 抽象 ...
随机推荐
- Unreal4教程总结
一些好的教程分享 Ue4大神的博客 http://www.tomlooman.com 关于CustomDepth的文章的翻译 http://gad.qq.com/program/translatevi ...
- linux mysql 安装配置
1.确认当前linux系统版本,使用以下命令: cat /etc/issue cat /etc/redhat-release 2.下载对应linux系统的mysql安装包. 下载地址:http://d ...
- HDU5800 To My Girlfriend(DP)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5800 Description Dear Guo I never forget the mom ...
- 单片机与控制实验(5)——重量测量并在LCD12864显示
一.实验目的和要求 掌握点阵式液晶显示屏的原理和控制方法,掌握点阵字符的显示方法.掌握模拟/数字(A/D)转换方式,进一步掌握使用C51语言编写程序的方法,使用C51语言编写实现重量测量的功能. 二. ...
- clientX .offsetX .screenX x 的区别
clientX 设置或获取鼠标指针位置相对于当前窗口的 x 坐标,其中客户区域不包括窗口自身的控件和滚动条. clientY 设置或获取鼠标指针位置相对于当前窗口的 y 坐标,其中客户区域不包括窗口自 ...
- linux常用命令总结
du -sh * 当前目录下所有文件占用空间大小,df 空间占用 top 资源使用情况 M 根据驻留内存大小进行排序 tail 1.tail -f filename说明:监视filename文件的尾 ...
- http服务的安装与配置
挂载光盘mount /dev/cdrom /y #y是挂载光盘的位置 使用yum命令进安装httpd服务 yum命令的配置文件, yum配置文件位于 /etc/yun.repos.d 目录 ...
- Struts2的OGNL表达式语言
一.OGNL的概念 OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者 ...
- 创建Chrome启动器
今天清理垃圾时不知怎么把chrome启动器删除了,现在要重新创建一个 1.在桌面创建一个chrome.exe的快捷键方式,属性更改目标为: "C:\Program Files (x86)\G ...
- JS中数组的操作[转]
1.数组的创建 var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限, ...