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 /** * 职责链模式 * * 为解除请求的发送者和接收者之间的耦合,而使用多个对象都用机会处理这个请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它 * 抽象 ...
随机推荐
- echarts之tooltip-showContent
当trigger:为'axis'时 tooltip : { trigger: 'axis', showContent:false } 当trigger:为'item'时 tooltip : { tri ...
- OpenLayers 3 之 地图样式(ol.style)详解
地图样式是由 style 类控制的,其包含了地图样式的方方面面,例如,填充色.图标样式.图片样式.规则图形样式.边界样式.文字样式等,样式一般针对矢量要素图层. 矢量图层样式可以事先写好,写成静态的, ...
- encodeURIComponent()中文乱码
可能是Tomcat的编码格式问题 应该在8080端口下设置 <Connector port="8080" protocol="HTTP/1.1" co ...
- memcache and redis 的区别
memcache和redis都属于缓存但是memcache的存储大小是收到 限制的memcache的 键值长度是250,内存的大小限制是1M并且memcache不支持数据的持久化缓存 redis支持五 ...
- 构建高性能的MYSQL数据库系统
实验环境: DB1:172.16.1.100 DB2:172.16.1.101 VRRIP:172.16.1.99 步骤: yum -y install mysql 1.修改DB1的mysql配置文件 ...
- (转)java自带线程池和队列详细讲解 - CSDN过天的专栏
一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后加入了java.util ...
- 代替jquery $.post 跨域提交数据的N种形式
跨域的N种形式: 1.直接用jquery中$.getJSON进行跨域提交 优点:有返回值,可直接跨域: 缺点:数据量小: 提交方式:仅get (无$.postJSON) $.getJSON(" ...
- ACM :漫漫上学路 -DP -水题
CSU 1772 漫漫上学路 Time Limit: 1000MS Memory Limit: 131072KB 64bit IO Format: %lld & %llu Submit ...
- Android api SmsMessage类createFromPdu(byte[] pdu) is depracted(不推荐使用,过时的)
我想实现一个,监听功能--当手机收到相关短信,触发一些时间,程序中 SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj); cr ...
- [svg翻译教程]椭圆(ellipse元素)和线(line元素)
line 先看个例子,这是svg中最简单的线 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http:/ ...