首页 > 学院 > 开发设计 > 正文

优雅就一个字——设计模式之数据上传接口

2019-11-17 03:14:41
字体:
来源:转载
供稿:网友

优雅就一个字——设计模式之数据上传接口

在网上看到很多关于设计模式的文章。但是基本都是单独讲解某一个设计模式的应用场景和设计思路。可是真实的项目中,可能仅仅只按照书上的某种设计模式就能写出优雅的代码吗?我觉得是不可能的。我这篇文章希望跟大家分享的是我思考的过程,而非结果。首先,应该对书上的20多种的设计模式有了解,大概清楚它们都是怎么样一个设计思路。建议有想学习设计模式的Friends还是买本纸质书系统的学习。下面,我给出一个真实的项目来引出我对这个项目的思考。第一次写博客分享我的思路,在加上我的思维有些女性思维,是跳跃性的。可能有些表达不是很清楚。望大家见谅。

    • 看到这流程图,首先在我脑海里的就是这是由一个一个小方块组合起来的组合体。我们先不管具体代码该怎么写,类怎么设计。只知道这是一个组合体。会有很多类。说到组合,我们是否可以联想到这应该是一个结构型的设计。这个组合体是由这些小方块代表的类按照某种结构组合起来的。结构型的设计模式有哪些,大家脑海里应该会有个轮廓了。
    • 又看到每一个小方块有分支,2个分支,分别代表正确的时的下一个流程和不正确时的下一个流程。这是不是意味着,我的方法会一层一层往下调用,直到最后一个小方块对象的下个流程对象为null时停止。想到这,我脑海里想到了装饰者模式和职责链模式。可是装饰者模式没有判断条件,它只是按照你组合的顺序,依次往下调用。那么这是不是更加符合职责链模式呢?咋一看很像,职责链模式是在一个流程内,没有处理的权限就往后传递,有处理权限就跳出方法链。跟我们的2个分支有些不同。我们的需求是要既有权限处理往后传递,没有权限也要往后传递。想到这,我们就清楚了,在小方块所代表的类里,应当有两个属性,一个是判断条件为True时的下一流程对象,另一个是判断条件为False时下一流程对象。这样,小方块类的类结构里就有了两个属性了。
      1. 每个小方块都有两个属性,我们是否就应该有个规范呢?所以我们定义一个接口,让所有的小方块代表的类实现这个接口。接口里目前有两个属性。
    • 接着又想,每个小方块代表的类,所执行的具体业务逻辑不一样,所以,我们在接口里是否应该有个方法可供子类重写呢?这样一来,每个小方块所代表的类都有了自己的业务逻辑。但是,那在什么地方调用下个流程的业务逻辑呢?如果放在单独的每个小方块所代表的类中,那岂不是,我们在每一个小方块类中都要写一些重复的调用下个流程的代码呢?这样就不够优雅了。所以,我想要调用过程在父级类里实现。为了实现小方块类的多态和调用下个流程的代码复用,就有了一个能够有方法实现的类。这个类又必须包含抽象方法。那所有流程的抽象基类出来了。这个抽象类实现之前定义的接口。其实这个接口要不要都无所谓啦,不过好像每个设计模式都是从接口开始,那么就保留一个接口吧。
    • 抽象类有了,每个子类重写的业务逻辑方法也有了。接下来,就是写调用被重写的业务逻辑的方法了。此处,大家应该可以想到是一个模板方法吧。但是,我们这里有两个分支,具体调用哪一个分支是由当前的小方块类决定的。这样一想,那这个调用下个小方块类的业务逻辑方法的代码岂不是只能写在具体的每个小方块类里了。这样不是很麻烦吗?我们要想一个办法,将这个过程放在抽象类里解决。鉴于最多也就两个分支,不是正就是反。那么我们是否可以通过在抽象类里设置一个属性,来标识下一流程具体调用的是哪一个分支呢?所以我们抽象类里又有了一个属性。这个属性是要被子类在业务逻辑方法中重新赋值的。
      1. 在抽象类的调用下一流程的方法里,我们会有一个判断,判断这个属性所代表的下一流程具体是哪一个分支。
    • 当某些业务处理完之后,可能就直接要结束整个流程,比如说,如果我第一步验证没通过,那么后面的流程都不能被执行。所以,我们要能够随时退出整个流程。这样,我们跟上面决定调用哪个分支的设计思路一致,加一个属性,来标识说是否要结束整个流程。可供子类重新赋值。在父类的调用下一个流程的方法中做判断。
  • 那现在我们的抽象类里就有了3个属性,2个方法。
    1. 当条件判断为True时的下一流程属性
    2. 当条件判断为False时的下一流程属性
    3. 标识下一流程调用哪一个分支的属性
    4. 标识是否结束整个流程的属性
    5. 封装了调用过程的方法
    6. 需要被重写的的具体业务逻辑方法
  • 然后,总有参数要传递到每一个小方块类的业务逻辑方法中吧。那么我们这里就将所有参数封装成一个数据实体类。依次传递到每个小方块类的业务逻辑方法中。大概思路就说到这吧。还有一些业务需求没有讲到,那在代码里都有体现。先上代码吧。

    /// <summary>    /// 处理流程基类    /// </summary>    public abstract class PRocessFlowBase : iprocessFlow    {        protected ProcessFlowBase(ProcessFlowBase processFlowWhenRight = default(ProcessFlowBase), ProcessFlowBase processFlowWhenWrong = default(ProcessFlowBase))        {            this.NextProcessFlowWhenRight = processFlowWhenRight;            this.NextProcessFlowWhenWrong = processFlowWhenWrong;            this.IsRight = true;            this.IsEnd = false;        }        protected IDbConnection DbConnection { get; set; }        protected IDbCommand DbCommand { get; set; }        protected IDbTransaction DbTransaction { private get; set; }        /// <summary>        /// 当前流程是否处理通过        /// </summary>        private bool IsRight { get; set; }        /// <summary>        /// 流程是否结束        /// </summary>        private bool IsEnd { get; set; }        /// <summary>        /// 下一个流程,当流程处理操作通过的时候        /// </summary>        private ProcessFlowBase NextProcessFlowWhenRight { set; get; }        /// <summary>        /// 下一个流程,当流程处理操作不通过的时候        /// </summary>        private ProcessFlowBase NextProcessFlowWhenWrong { get; set; }        /// <summary>        /// 处理        /// </summary>        /// <param name="dataContext"></param>        public void Process(DataContext dataContext)        {            this.ProcessTemplate(dataContext);            this.RecordLog(dataContext);            if (this.IsEnd) return;            if (this.IsRight)            {                if (this.NextProcessFlowWhenRight == default(ProcessFlowBase)) return;                this.NextProcessFlowWhenRight.SetParameters(this.DbConnection, this.DbCommand, this.DbTransaction);                this.NextProcessFlowWhenRight.Process(dataContext);            }            else            {                if (this.NextProcessFlowWhenWrong == default(ProcessFlowBase)) return;                this.NextProcessFlowWhenWrong.SetParameters(this.DbConnection, this.DbCommand, this.DbTransaction);                this.NextProcessFlowWhenWrong.Process(dataContext);            }        }        /// <summary>        /// 流程处理模板方法,供子类实现        /// </summary>        /// <param name="dataContext"></param>        protected abstract void ProcessTemplate(DataContext dataContext);        /// <summary>        /// 记录日志,供子类实现        /// </summary>        /// <param name="dataContext"></param>        protected virtual void RecordLog(DataContext dataContext)        {            LogHelper.Record(dataContext);        }        /// <summary>        /// 结束本次流程        /// </summary>        protected void EndProcessFlow()        {            this.IsEnd = true;        }        /// <summary>        /// 确定下一流程,后续候选流程名单在调用构造函数的时候已经初始化好        /// </summary>        /// <param name="rightFlowOrWrongFlow"></param>        protected void SetNextFlow(RightFlowOrWrongFlow rightFlowOrWrongFlow)        {            this.IsRight = rightFlowOrWrongFlow == RightFlowOrWrongFlow.Right;        }        /// <summary>        /// 回滚操作流程        /// </summary>        protected void RollBackProcessFlow()        {            this.DbTransaction.Rollback();            this.DbConnection.Close();        }        /// <summary>        /// 提交事物操作        /// </summary>        protected void CommitProcessFlow()        {            this.DbTransaction.Commit();            this.DbConnection.Close();        }        /// <summary>        /// 设置下一流程单例属性        /// </summary>        /// <param name="param"></param>        private void SetParameters(params object[] param)        {            var dbConnection = param[0] as IDbConnection;            var dbCommand = param[1] as IDbCommand;            var dbTransaction = param[2] as IDbTransaction;            this.DbConnection = dbConnection;            this.DbCommand = dbCommand;            this.DbTransaction = dbTransaction;        }    }

    /// <summary>    /// 检验授权码流程,此流程应当作为所有业务流程的入口流程。会在此类中做一些特别的处理    /// </summary>    public class CheckToken : ProcessFlowBase    {        public CheckToken(ProcessFlowBase processFlowWhenRight = default(ProcessFlowBase),            ProcessFlowBase processFlowWhenWrong = default(ProcessFlowBase))            : base(processFlowWhenRight, processFlowWhenWrong)        {            //这个流程作为所有业务处理的入口流程,所以,我在这里要写入一段初始化流程事务对象的代码,仅执行一次            base.DbConnection = LogHelper.CreateDbConnection();            base.DbConnection.Open();            base.DbCommand = base.DbConnectio
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表