十六.行为型设计模式——Chain of Responsibility(责任链模式)

  • 定义

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

  UML类图如下:

  

  其中类和对象的关系:

  1. Handler(传递者接口):定义一个处理请求的接口;实现链中下一个对象(可选)。

  2. ConcreteHandler(具体传递者):处理它所负责的请求;可以访问链中下一个对象;如果可以处理请求,就处理它,否则将请求转发给后续者。

  3. Client(客户应用程序):向链中的对象提出最初的请求。

  典型应用的顺序图如下:

  

  • 实例1——采购分级审批

  一般的企业采购审批都是分级的,采购量的不同就需要不同层次的主管人员来审批,如主任可以审批1万元以下的采购单,副董事长可以审批2.5万元以下的采购单,董事长可以审批10万元以下的采购单,10万元以上的就要开会判定。UML类图如下:

  

  

代码
 
   
// 抽象传递者
abstract class Approver
{
protected string name;
protected Approver successor; // 上级
public Approver( string name)
{
this .name = name;
}
public void SetSuccessor(Approver successor)
{
this .successor = successor;
}
abstract public void ProcessRequest(PurchaseRequest request);
}
// 具体传递者—主任
class Director : Approver
{
public Director( string name) : base (name) { }
public override void ProcessRequest(PurchaseRequest request)
{
// 总额小于10000就处理
if (request.Amount < 10000.0 )
{
Console.WriteLine(
" {0} {1} 审批了采购请求#{2} " , " 主任 " , name, request.Number);
}
else if (successor != null )
{
successor.ProcessRequest(request);
}
}
}
// 具体传递者—副董事长
class VicePresident : Approver
{
public VicePresident( string name) : base (name) { }
public override void ProcessRequest(PurchaseRequest request)
{
// 总额小于25000就处理
if (request.Amount < 25000 )
{
Console.WriteLine(
" {0} {1} 审批了采购请求#{2} " , " 副董事长 " , name, request.Number);
}
else if (successor != null )
{
successor.ProcessRequest(request);
}
}
}
// 具体传递者—董事长
class President : Approver
{
public President( string name) : base (name) { }
public override void ProcessRequest(PurchaseRequest request)
{
// 总额小于100000就处理
if (request.Amount < 100000 )
{
Console.WriteLine(
" {0} {1} 审批了采购请求#{2} " , " 董事长 " , name, request.Number);
}
else
{
Console.WriteLine(
" 采购请求#{0}需要开会来决定! " , request.Number);
}
}
}


// 采购单
class PurchaseRequest
{
private int number;
private double amount;
private string purpose;
public PurchaseRequest( int number, double amount, string purpose)
{
this .number = number;
this .amount = amount;
this .purpose = purpose;
}

public int Number
{
get { return number; }
set { number = value; }
}
public double Amount
{
get { return amount; }
set { amount = value; }
}
public string Purpose
{
get { return purpose; }
set { purpose = value; }
}
}

// 客户应用测试
class Client
{
[STAThread]
static void Main( string [] args)
{
Director Larry
= new Director( " Larry " );
VicePresident Sam
= new VicePresident( " Sam " );
President Tammy
= new President( " Tammy " );
Larry.SetSuccessor(Sam);
Sam.SetSuccessor(Tammy);
PurchaseRequest rs
= new PurchaseRequest( 2034 , 350 , " Supplies " );
Larry.ProcessRequest(rs);
PurchaseRequest rx
= new PurchaseRequest( 2035 , 35000 , " Proejct X " );
Larry.ProcessRequest(rx);
PurchaseRequest ry
= new PurchaseRequest( 2036 , 350000 , " Proejct Y " );
Larry.ProcessRequest(ry);
Console.Read();
}
}
  • 实例2——智能大厦安全系统

  假定我们要做一个智能大厦安全系统。安全系统包括很多各种传感器(运动检测器、烟感检测器、温度检测器),它们的状态会传给计算机。计算机系统的工作是记录这些状态并在紧急事件发生事发出警报。我们设计的系统要有高度可扩展性,它可以适用于小型零售店、办公楼、仓库、多功能大厦等多种场合。

  我们的监控程序会为每一个传感器实例生成一个对象,而所在的安全区域会分为区域(Area)、仓库(Warehouse)和大楼(Building)。我们假定安全系统中仓库的办公室一旦温度超过150摄制度就要打开喷洒器喷水,然后系统会通知仓库保安去现场检查,系统在仓库所在大楼发出火警。

  其UML类图如下:

  

代码
 
   
// 让我们先定义传感器抽象类
public abstract class Sensor
{
// 所安装的位置
public string position;
}
// 温度传感器
public class TemperatureSensor : Sensor
{
public TemperatureSensor( string position)
{
this .position = position;
}
}

// 定义安全区抽象类
public abstract class SecurityZone
{
// 父区域
private SecurityZone parent;
// 区域名
public string name;
public SecurityZone( string name)
{
this .name = name;
}
// 返回它的父区域
public SecurityZone GetParent()
{
return parent;
}
// 设定它的负区域
public void SetParent(SecurityZone zone)
{
this .parent = zone;
}

// 调用这个方法去通知区域对象其中的传感器的测量值
public void Notify( int measurement, Sensor sensor)
{
if ( ! HandleNotification(measurement, sensor) && parent != null )
parent.Notify(measurement, sensor);
}
// 上面的方法notify调用这个方法让对象可以处理测量值
public abstract bool HandleNotification( int measurement, Sensor sensor);

// 本方法被子区域调用来报告火警,期待子区域中打开喷洒器
// 重载此方法可以让父区域也采取必要的行动
public virtual void FireAlarm(SecurityZone zone, Sensor sensor)
{
Console.WriteLine(
this .name + sensor.position + " 水喷洒器打开了 " );
if (parent != null )
{
parent.FireAlarm(zone, sensor);
}
}
}
// 具体区域,继承SecurityZone类
public class Area : SecurityZone
{
public Area( string name) : base (name) { }
public override bool HandleNotification( int measurement, Sensor sensor)
{
if (measurement > 150 )
{
FireAlarm(
this , sensor);
return true ;
}
return false ;
}
}
// 具体区域,仓库类,有火时,呼叫保安马上检查发货区域
public class Warehouse : SecurityZone
{
public Warehouse( string name) : base (name) { }
// 仓库下的区域已经处理传感器的测量值,这里不作处理
public override bool HandleNotification( int measurement, Sensor sensor)
{
return false ;
}
public override void FireAlarm(SecurityZone zone, Sensor sensor)
{
if (zone.GetType() == typeof (Area))
{
Console.WriteLine(
" 保安请马上去检查{0}的{1} " , this .name, zone.name);
if (GetParent() != null )
GetParent().FireAlarm(zone, sensor);
return ;
}
base .FireAlarm(zone, sensor);
}
}
// 具体区域,大楼类,采取行动,通报火警
public class Building : SecurityZone
{
public Building( string name) : base (name) { }
public override bool HandleNotification( int measurement, Sensor sensor)
{
return false ;
}
public override void FireAlarm(SecurityZone zone, Sensor sensor)
{
if (zone.GetType() == typeof (Area))
{
Console.WriteLine(
" {0}栋大楼发生火警 " , this .name);
if (GetParent() != null )
GetParent().FireAlarm(zone, sensor);
return ;
}
base .FireAlarm(zone, sensor);
}
}

// 客户应用测试
class Client
{
[STAThread]
static void Main( string [] args)
{
Area a
= new Area( " 经理室 " );
Warehouse w
= new Warehouse( " 仓库B " );
TemperatureSensor ts_at_corner
= new TemperatureSensor( " 右边角 " );
a.SetParent(w);
// 区域a在仓库w中
Building b = new Building( " #2 " );
w.SetParent(b);
// 仓库w在大楼b中
a.Notify( 200 , ts_at_corner);
Console.Read();
}
}

 

  • 优势和缺陷

  责任链模式可以减少对象的连接,为对象责任分配增加了很大的灵活性。该模式允许把一组类作为一个类来使用,并且在类的组合中,一个类的事件可以发送到另一个类并由其处理。

  责任链模式通常应用与图形用户界面中,窗体的部件可能会包含其他几个小部件,就如同Windows窗体应用程序中,控件中又可以放置其他控件,控件边界会决定是否处理事件,或者将事件传递给父控件来处理。

  另外,责任链还会以树状出现,这样,一个事件可以传给多个类,或者,多个类的信息可以提交到一个类。树状责任链能够提供更灵活的技巧,但缺点是信息在树中容易迷失。

  • 应用情景

  下面的情景很适合应用责任链模式:

  1. 超过一个对象能够处理客户请求并且到底哪个对象处理预先不知道。

  2. 一个请求可以发布到多个对象但它的接收都是不清晰。

  3. 可以动态指定一组对象处理请求。

转载于:https://www.cnblogs.com/vrliym/archive/2010/11/14/1877270.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值