设计模式之责任链模式(C#实现)

使用场景

     什么时候应该使用责任链模式?
     这种模式最佳的使用场景是,你的业务上有一个逻辑上的处理链,这个处理链每次必须按照顺序运行。这里请注意,链分叉是这种模式的一个变体, 
     但是很快处理起来就会非常复杂。因此,当我对现实世界中“命令链”场景建模的时候,我通常会使用这种模式。
     这就是我以银行为例的原因,因为它就是现实世界中可以用代码建模的“责任链”。

示例

  这里假设我们拥有一家银行,银行里面有3个级别的员工,分别是“柜员”、“主管”、“银行经理”。如果有人来取款,“柜员”只允许10,000美元以下的取款操作。
        如果金额超过10,000美元,那么它的请求将传递给“主管”。“主管”可以处理不超过100,000美元的请求,但前提是该账户在必须有身份证ID。
        如果没有身份证ID,则当前请求必须被拒绝。如果取款金额超过100,000美元,则当前请求可以转交给“银行经理”,“银行经理”可以批准任何取款金额,
        因为如果有人取超过100,000美元的金额,他们就是VIP, 我们不在乎VIP的身份证ID和其他规定。

糟糕的实现, if/else地狱

    // <summary>
    // 糟糕的实现, if/else地狱
    // </summary>
    class BankAccount
    {
        bool idOnRecord { get; set; }

        void WithdrawMoney(decimal amount)
        {
            // 柜员处理
            if (amount < 10000)
            {
                Console.WriteLine("柜员提取的金额");
            }
            // 主管处理
            else if (amount < 100000)
            {
                if (!idOnRecord)
                {
                    throw new Exception("客户没有身份证ID");
                }

                Console.WriteLine("主管提取的金额");
            }
            else
            {
                Console.WriteLine("银行经理提取的金额");
            }
        }
    }

责任链模式实现

    /// 什么时候应该使用责任链模式?
    /// 这种模式最佳的使用场景是,你的业务上有一个逻辑上的处理链,这个处理链每次必须按照顺序运行。这里请注意,链分叉是这种模式的一个变体, 
    /// 但是很快处理起来就会非常复杂。因此,当我对现实世界中“命令链”场景建模的时候,我通常会使用这种模式。
    /// 这就是我以银行为例的原因,因为它就是现实世界中可以用代码建模的“责任链”。
    static class ChainOfResponsibility
    {
        public static void StartTest()
        {
            var bankManager = new BankManager();

            var bankSupervisor = new Supervisor();
            bankSupervisor.SetLineManager(bankManager);

            var frontLineStaff = new Teller();
            frontLineStaff.SetLineManager(bankSupervisor);

            //模拟客户取款,从柜员开始处理取款请求
            frontLineStaff.HandleWithdrawRequest(new BankAccount() { idOnRecord = true }, 100000);
        }
    }

    //柜员
    class Teller : BankEmployee, IBankEmployee
    {
        protected override bool CanHandleRequest(BankAccount account, decimal amount)
        {
            if (amount > 10000)
            {
                return false;
            }
            return true;
        }

        protected override void Withdraw(BankAccount account, decimal amount)
        {
            Console.WriteLine($"柜员提取了金额,金额为: {amount}");
        }
    }

    //主管
    class Supervisor : BankEmployee, IBankEmployee
    {
        protected override bool CanHandleRequest(BankAccount account, decimal amount)
        {
            if (amount > 100000)
            {
                return false;
            }
            return true;
        }

        protected override void Withdraw(BankAccount account, decimal amount)
        {
            if (!account.idOnRecord)
            {
                throw new Exception("客户没有身份证ID");
            }

            Console.WriteLine($"主管提取了金额,金额为: {amount}");
        }
    }

    //银行经理
    class BankManager : BankEmployee, IBankEmployee
    {
        protected override bool CanHandleRequest(BankAccount account, decimal amount)
        {
            return true;
        }

        protected override void Withdraw(BankAccount account, decimal amount)
        {
            Console.WriteLine($"银行经理提取了金额,金额为: {amount}");
        }
    }

    /// <summary>
    /// 定义银行雇员接口,约束雇员行为,实现多态
    /// LineManager: 雇员的上级
    /// HandleWithdrawRequest: 处理客户的取款请求
    /// </summary>
    interface IBankEmployee
    {
        IBankEmployee LineManager { get; }
        void HandleWithdrawRequest(BankAccount account, decimal amount);
    }

    /// <summary>
    /// 定义银行雇员抽象类,实现HandleWithdrawRequest方法,每个实现类都需要使用它,比接口的多态性多了复用的功能
    /// SetLineManager(): 设置自身的上级
    /// CanHandleRequest抽象方法:判断自身是否能处理客户的取款请求,子类必须实现
    /// Withdraw抽象方法:取款方法
    /// </summary>
    abstract class BankEmployee : IBankEmployee
    {
        public IBankEmployee LineManager { get; private set; }

        public void SetLineManager(IBankEmployee lineManager)
        {
            this.LineManager = lineManager;
        }

        public void HandleWithdrawRequest(BankAccount account, decimal amount)
        {
            if (CanHandleRequest(account, amount))
            {
                Withdraw(account, amount);
            }
            else
            {
                LineManager.HandleWithdrawRequest(account, amount);
            }
        }

        abstract protected bool CanHandleRequest(BankAccount account, decimal amount);

        abstract protected void Withdraw(BankAccount account, decimal amount);
    }

    /// <summary>
    /// 银行账号类
    /// </summary>
    class BankAccount
    {
        //判断客户是否有身份ID号
        public bool idOnRecord { get; set; }

        //public void WithdrawMoney(IBankEmployee frontLineStaff, decimal amount)
        //{
        //    frontLineStaff.HandleWithdrawRequest(this, amount);
        //}
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值