C#机房重构:职责链模式

前言:前阵子拖着没弄完的机房重构这次重新完善,发现有一些设计模式并没有体现出来,所以今天加了一个职责链模式

 

机房重构中,上机的过程需要经过诸多判断,因此这个过程使用职责链模式是完全可以的。

 

我们先梳理一下逻辑:上机之前需要先判断该卡号是否存在,之后判断卡号的余额,最后判断该卡是否正在上机,最后执行上机操作。(这是本人的思路,仅供参考)按照这个思路,我们往下进行。

 

首先建立职责链项目,新建引用(Entity、IDAL、DAL,仅供参考),建立以下类

C#机房重构:职责链模式_第1张图片

Handler类是一个抽象类,用来被子类重写和设置子类方法的后继方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data;

namespace ChainModel
{
    public abstract class Handler
    {
        protected _5.IDAL.OnlineIDAL idal;

        protected Handler successor;

        //构造函数
        public Handler(_5.IDAL.OnlineIDAL idal)
        {
            this.idal = idal;
        }

        //设置下一个处理对象
        public void SetSuccessor(Handler successor)
        {
            this.successor = successor;
        }

        //抽象处理方法,使子类重写它,实现不同行为,多态的原理
        public abstract void HandlerRequest(_7.Entity.OnlineEntity cardid);
    }
}

*设置Handler的参数为IDAL层是为了能够调用DAL层的方法获取相应参数进行判断,而又保证代码的低耦合。

 

下一步建立Chain_IsCardid类,继承Handler类,在里面写好逻辑判断。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data;

namespace ChainModel
{
    public class Chain_IsCardid:Handler
    {
        public Chain_IsCardid(_5.IDAL.OnlineIDAL idal) : base(idal) { }
        
        //重写父类方法,体现多态
        public override void HandlerRequest(_7.Entity.OnlineEntity cardid)
        {
            //调用IDAL层查询卡号的方法
            DataTable iscardid = idal.ViewCardID(cardid);

            if(iscardid.Rows.Count == 0)
            {
                throw new Exception("没有这个卡号!");
            }
            else
            {
                successor.HandlerRequest(cardid);
            }
        }
    }
}

之后建立Chain_IsCash类,判断是否余额不足

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _7.Entity;

using System.Data;

namespace ChainModel
{
    public class Chain_IsCash:Handler
    {
        public Chain_IsCash(_5.IDAL.OnlineIDAL idal) : base(idal) { }

        public override void HandlerRequest(_7.Entity.OnlineEntity cardid)
        {
            //调用IDAL层查询余额的方法与基本信息的方法
            DataTable iscash = idal.ViewCardCash(cardid);
            DataTable table = idal.DALViewLimitCash(cardid);

            if(Convert.ToDouble(iscash.Rows[0]["cash"]) < Convert.ToDouble(table.Rows[0]["limitCash"]))
            {
                throw new Exception("余额不足!");
            }
            else
            {
                successor.HandlerRequest(cardid);
            }
        }
    }
}

下一步建立Chain_IsOnline,判断是否上机

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _7.Entity;

using System.Data;

namespace ChainModel
{
    public class Chain_IsOnline:Handler
    {
        public Chain_IsOnline(_5.IDAL.OnlineIDAL idal) : base(idal) { }

        public override void HandlerRequest(_7.Entity.OnlineEntity cardid)
        {
            DataTable table = idal.ViewCardState(cardid);

            if(table.Rows.Count > 0)
            {
                throw new Exception("该用户正在上机!");
            }
            else
            {
                return;
            }
        }
    }
}

本来开始是想把上机的操作也放到职责链中,但因为引用的问题(不知道为什么不能引用UI层,不能引用就不能调用UI层的控件进行操作),所以没有放进来。机房合作的时候注意这个问题!

 

职责链弄好之后,我们在BLL层调用职责链模式,并设定后继方法的顺序链与开始执行的位置:

//职责链模式 上机,新增职责链模式上机方法
public DataTable Online_model(_7.Entity.OnlineEntity cardid)
{
        //实例化工厂层
        _4.Factory.OnlineFactory onlineFactory = new _4.Factory.OnlineFactory();

        _5.IDAL.OnlineIDAL idal = onlineFactory.CreateStudent();

        //职责链模式

        //1.创建具体处理对象,实例化时把“处理的具体执行者”-idal传过去
        ChainModel.Chain_IsCardid iscardid = new ChainModel.Chain_IsCardid(idal);
        ChainModel.Chain_IsCash iscash = new ChainModel.Chain_IsCash(idal);
        ChainModel.Chain_IsOnline isonline = new ChainModel.Chain_IsOnline(idal);

        //2.从底层设置上一级,逐级设置
        iscardid.SetSuccessor(iscash);
        iscash.SetSuccessor(isonline);
            
        //3.从链的底层开始执行
        iscardid.HandlerRequest(cardid);
        return idal.ViewCardState(cardid);
}

之后在Facade层调用B层减少耦合,最后在U层调用F层的语句,加入上机后需要的操作,就完成了!

public class OnlineFacade
{
    //实例化BLL层
    _3.BLL.OnlineBLL onlineBLL = new _3.BLL.OnlineBLL();
    
    //调用B层职责链上机方法
    public DataTable FacadeOnline(_7.Entity.OnlineEntity cardid)
    {
        DataTable table = onlineBLL.Online_model(cardid);
        return table;
    }
}
private void btnonline_Click(object sender, EventArgs e)
{
        //调用F层职责链方法
        DataTable online = onlineFacade.FacadeOnline(onlineStudent);

        timerdynamicdetect.Enabled = true;//实时监控时钟开始运行
        timerdynamictime.Enabled = true;//动态时间时钟开始运行

        lblondate.Text = DateTime.Now.ToString("yyyy-MM-dd");//lblondate获取当前日期
        lblontime.Text = DateTime.Now.ToString("HH:mm:ss");//lnlontime获取当前时间

        //将上机时间日期与用户类型传给实体层
        onlineStudent.State = "上机";
        onlineStudent.OnDate = Convert.ToDateTime(lblondate.Text);
        onlineStudent.OnTime = Convert.ToDateTime(lblontime.Text);

        //余额与消耗时间都先为0
        lblconsumetime.Text = "0";
        lblconsumecash.Text = "0";

        //下机时间与日期也变为0
        lbloffdate.Text = "";
        lblofftime.Text = "";

        //调用外观层方法-修改用户上机状态
        onlineFacade.ModifyOnlineState(onlineStudent);

        MessageBox.Show("上机成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);

        //下机按钮可用
        btnoffline.Enabled = true;
}

 

 

结尾:之前单纯学习设计模式的时候都能理解,但实际应用,还是在又有Class类又有Winform类的七层中使用还是会阻碍重重,比如引用、不同类型的转换,就比如我这里为了省事,几个子类职责链内返回的参数都是DataTable类。这些如果不琢磨透的话,一开始很容易吃大亏的。

你可能感兴趣的:(C#机房重构:职责链模式)