设计模式复习(十五)-------职责链模式

1. 职责链模式简介

在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显式指定,将必不可少地带来请求发送者与接受者之间的紧耦合。
如何使请求的发送者不需要指定具体的接受者?让请求的接受者在运行时决定谁来处理请求,从而使两者解耦。

职责链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。
避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
——《设计模式》GoF

2. 结构

在这里插入图片描述

  • 抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。
  • 具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

典型的抽象处理者代码:

abstract class Handler{
	//维持对下家的引用
    protected Handler successor;
	
	public void SetSuccessor(Handler successor){this.successor = successor;}
	
	public abstract void HandleRequest(string request);
}

典型的具体处理者代码:

class ConcreteHandler : Handler {
	public override void HandleRequest(string request){
		if (请求满足条件){
			//处理请求
		}
		else{
			this.successor.HandleRequest(request);  //转发请求
		}
	}
}

典型的客户端代码:

……
Handler handler1, handler2, handler3;
handler1 = new ConcreteHandlerA();
handler2 = new ConcreteHandlerB();
handler3 = new ConcreteHandlerC();
//创建职责链
handler1.SetSuccessor(handler2);
handler2.SetSuccessor(handler3);
//发送请求,请求对象通常为自定义类型
handler1.HandleRequest("请求对象");
……

3. 示例

某企业的SCM(Supply Chain Management,供应链管理)系统中包含一个采购审批子系统。该企业的采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批,主任可以审批5万元以下(不包括5万元)的采购单,副董事长可以审批5万元至10万元(不包括10万元)的采购单,董事长可以审批10万元至50万元(不包括50万元)的采购单,50万元及以上的采购单就需要开董事会讨论决定。
现使用职责链模式设计并实现该系统。

在这里插入图片描述

示例代码
(1) PurchaseRequest:采购单类,充当请求类
(2) Approver:审批者类,充当抽象处理者
(3) Director:主任类,充当具体处理者
(4) VicePresident:副董事长类,充当具体处理者
(5) President:董事长类,充当具体处理者
(6) Congress:董事会类,充当具体处理者
(7) Program:客户端测试类

namespace CoRSample{
    /// 采购请求--具体处理请求--封装与请求相关的数据
    class PurchaseRequest{
        private double amount;  //采购金额
        private int number;  //采购单编号
        private string purpose;  //采购目的

        public PurchaseRequest(double amount, int number, string purpose){
            this.amount = amount;
            this.number = number;
            this.purpose = purpose;
        }

        public double Amount{
            get { return amount; }
            set { amount = value; }
        }

        public int Number{
            get { return number; }
            set { number = value; }
        }

        public string Purpose{
            get { return purpose; }
            set { purpose = value; }
        }
    }
}

namespace CoRSample{
    /// 抽象处理者
    abstract class Approver{
        protected Approver successor; //定义后继对象
        protected string name; //审批者姓名

        public Approver(string name){this.name = name;}

        //设置后继者
        public void SetSuccessor(Approver successor){
            this.successor = successor;
        }

        //抽象请求处理方法
        public abstract void ProcessRequest(PurchaseRequest request);
    }
}

namespace CoRSample{
    /// 董事会--具体处理者
    class Congress : Approver{
        public Congress(string name) : base(name){}

        //具体请求处理方法
        public override void ProcessRequest(PurchaseRequest request) {
 		    Console.WriteLine("召开董事会审批采购单:{0},金额:{1}元,采购目的:{2}。",request.Number, request.Amount, request.Purpose);	    //处理请求
 	    }  
    }
}
namespace CoRSample{
    /// 主任--具体处理者
    class Director : Approver{
        public Director(string name) : base(name){}

        //具体请求处理方法
        public override void ProcessRequest(PurchaseRequest request) {
 		    if (request.Amount < 50000) {
                Console.WriteLine("主任{0}审批采购单:{1},金额:{2}元,采购目的:{3}。", this.name, request.Number, request.Amount, request.Purpose);  //处理请求
 		    }
 		    else {
 			    this.successor.ProcessRequest(request);  //转发请求
 		    }	
 	    }
    }
}
namespace CoRSample{
    /// 经理--具体处理者
    class Manager : Approver{
        public Manager(string name) : base(name){}
        //具体请求处理方法
        public override void ProcessRequest(PurchaseRequest request) {
 		    if (request.Amount < 80000) {
 			    Console.WriteLine("经理{0}审批采购单:{1},金额:{2}元,采购目的:{3}。", this.name, request.Number, request.Amount, request.Purpose);  //处理请求
 		    }
 		    else {
 			    this.successor.ProcessRequest(request);  //转发请求
 		    }
 	    }
    }
}
namespace CoRSample{
    /// 董事长--具体处理者
    class President : Approver{
        public President(string name) : base(name){}

        //具体请求处理方法
        public override void ProcessRequest(PurchaseRequest request) {
 		    if (request.Amount < 500000) {
 			    Console.WriteLine("董事长{0}审批采购单:{1},金额:{2}元,采购目的:{3}。", this.name, request.Number, request.Amount, request.Purpose);  //处理请求
 		    }
 		    else{
 			    this.successor.ProcessRequest(request);  //转发请求
 		    }
 	    }
    }
}
namespace CoRSample{
    /// 副董事长--具体处理者
    class VicePresident : Approver{
        public VicePresident(string name) : base(name){}

        //具体请求处理方法
        public override void ProcessRequest(PurchaseRequest request) {
 		    if (request.Amount < 100000) {
                Console.WriteLine("副董事长{0}审批采购单:{1},金额:{2}元,采购目的:{3}。", this.name, request.Number, request.Amount, request.Purpose);  //处理请求
 		    }
 		    else {
 			    this.successor.ProcessRequest(request);  //转发请求
 		    }	
 	    }
    }
}

namespace CoRSample{
    class Program{
        /// 客户端程序
        /// <param name="args"></param>
        static void Main(string[] args){
            Approver wjzhang, gyang, jguo, meeting,manager;

            //创建具体处理者
            wjzhang = new Director("张无忌");
            gyang = new VicePresident("杨过");
            jguo = new President("郭靖");
            meeting = new Congress("董事会");
            manager=new Manager("张三");

            //创建职责链----职责链的顺序取决于条件的判断方式
            wjzhang.SetSuccessor(manager);
            manager.SetSuccessor(gyang);
            gyang.SetSuccessor(jguo);
            jguo.SetSuccessor(meeting);


            //创建采购单
            PurchaseRequest pr1 = new PurchaseRequest(45000, 10001, "购买倚天剑");
            wjzhang.ProcessRequest(pr1);

            PurchaseRequest pr2 = new PurchaseRequest(60000, 10002, "购买《葵花宝典》");
            wjzhang.ProcessRequest(pr2);

            PurchaseRequest pr3 = new PurchaseRequest(160000, 10003, "购买《金刚经》");
            wjzhang.ProcessRequest(pr3);

            PurchaseRequest pr4 = new PurchaseRequest(800000, 10004, "购买桃花岛");
            wjzhang.ProcessRequest(pr4);

            PurchaseRequest pr5 = new PurchaseRequest(90000, 10005, "xxxxxx");
            wjzhang.ProcessRequest(pr5);

            Console.Read();
        }
    }
}

4. 分析与总结

职责链模式优点:

  • 使得一个对象无须知道是其他哪一个对象处理其请求,降低了系统的耦合度;

  • 可简化对象之间的相互连接;

  • 给对象职责的分配带来更多的灵活性;

  • 增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可

职责链模式缺点:

  • 不能保证请求一定会被处理;
  • 对于比较长的职责链,系统性能将受到一定影响,在进行代码调试时不太方便;
  • 如果建链不当(SetSuccessor使用不当),可能会造成循环调用,将导致系统陷入死循环。

职责链模式适用环境:

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定;
  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
  • 可动态指定一组对象处理请求。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值