探讨跨客户业务处理模式

背景

  目前系统中,有一个服务,此服务用于客户供应商的绩效。服务设计之初,只支持一家客户。

缺点分析

随着客户的增加以及每个客户的处理越来越个性化,原来服务设计已经补满足。此服务一共分为5个步骤。步骤一,步骤二……..,每个步骤出错,可以从上一个步骤继续。每次从当前步骤升级到下一个步骤,需要判断是否能满足升级条件。

现在由于客户的增加,每个客户的每个步骤里的处理逻辑不一致。

 

解决办法

  1. 设计模式之:模板方法模式

采购模板方法模式,不同客户继承相同的模板,各自实现自己的业务

    2.设计模式之:策略模式

最近又接到一个新的需要,要求每个客户本身根据厂区的不同产生不同的处理逻辑,由于前期的设计局限,所以只能在现有设计上继续补充

 

结合项目:策略模式在什么时候使用呢?策略模式在每个客户的实现哪里使用,通过抽象出接口,然后达到不同的厂区,调用的逻辑也不一样

 

代码演示:

其中的一个模板

using ESIC.RFQ.BizInterface.PerformanceCalculation;
using ESIC.RFQ.Common.CustomAttribute;
using ESIC.RFQ.Common.CustomExtend;
using ESIC.RFQ.Common.IOC;
using ESIC.SRM.Service.SupplierPerformance.Base;
using ESIC.SRM.Service.SupplierPerformance.Decorator;
using SRM.Dto.CustomEnum.SupplierCustomEnum;
using System;

namespace ESIC.SRM.Service.SupplierPerformance.Template
{

    /// <summary>
    /// Functional Description:获取需要的基础数据
    /// Creater:ZhangQC
    /// Date:2018/4/11 15:12:03
    /// </summary>
    public abstract class GetBaseDataTemplate : BaseDecorator
    {
        /// <summary>
        /// 基础类
        /// </summary>
        BaseRoots _baseRoots;

        /// <summary>
        /// Functional Description:构造函数
        /// Creater:ZhangQC
        /// Date: 2018/4/12 14:39
        /// </summary>
        protected GetBaseDataTemplate(BaseRoots baseRoots):base(baseRoots)
        {
            this._baseRoots = baseRoots;
        }

        /// <summary>
        /// Functional Description:记录当前步骤
        /// Creater:ZhangQC
        /// Date: 2018/4/12 14:40
        /// </summary>
        public override void WriteLog()
        {
            Log.Debug("当前步骤:进入获取基础数据");
        }


        /// <summary>
        /// Functional Description:从用户上传文件获取数据
        /// Creater:ZhangQC
        /// Date: 2018/4/11 16:48
        /// </summary>
        protected abstract bool FromUpload();


        /// <summary>
        /// Functional Description:从外部接口获取数据
        /// Creater:ZhangQC
        /// Date: 2018/4/11 16:49
        /// </summary>
        protected abstract bool FromInterface();


        /// <summary>
        /// Functional Description:从系统获取数据
        /// Creater:ZhangQC
        /// Date: 2018/4/11 16:49
        /// </summary>
        protected abstract bool FromSystemData();
      

        /// <summary>
        /// Functional Description:获取基础数据
        /// Creater:ZhangQC
        /// Date: 2018/4/11 16:49
        /// </summary>
        private bool GetBaseData()
        {
            return 
                FromUpload() & 
                FromSystemData();
        }

        /// <summary>
        /// Functional Description:开始获取基础数据
        /// Creater:ZhangQC
        /// Date: 2018/4/12 9:00
        /// </summary>
        public  void Start()
        {
            try
            {
                _baseRoots.WriteLog();
                WriteLog();
                //1.0不是当前步骤直接返回
                if (GetExecutionStep() != (int) ExecutionStepEnum.ProcessFiles) return;
                //1.1是当前步骤,执行状态是已完成,判断是否满足升级条件。满足=》升级,修改执行状态,不满足,继续在当前步骤等待,直到满足
                if (GetExecutionStatus() == (int) ExecutionStatusEnum.End)
                {
                    if (IocFactory.Resolve<IBaseRoots>().IsMeetTheUpgrade(OrgId, CalcVersion, ExecutionStepEnum.ProcessFiles, IpCount))
                    {
                        //重写下一个执行步骤
                        ExecutionStep(ExecutionStepEnum.EarlyPeriod.Value().ToString());
                        var nextExecutionStatus = ExecutionStatusEnum.Start.Value().CToString();
                        ExecutionStatus(nextExecutionStatus);
                    }
                    else
                    {
                        Log.Debug("当前步骤:获取数据未满足升级要求");
                    }

                    return;
                }
                //1.2是当前步骤,执行状态初始化,退出
                if (GetExecutionStatus() == (int) ExecutionStatusEnum.Init) return;

                //1.3是当前步骤,执行状态是开始状态,执行
                var getBaseDataFlag = GetBaseData();
                if (getBaseDataFlag)
                {
                    //执行完成,修改状态为完成状态
                    var executionStatus = ExecutionStatusEnum.End.Value().CToString();
                    ExecutionStatus(executionStatus);
                    //判断是否满足升级 。满足=》升级,修改执行状态;不满足=》继续在当前步骤等待。直到满足
                    if (IocFactory.Resolve<IBaseRoots>().IsMeetTheUpgrade(OrgId, CalcVersion, ExecutionStepEnum.ProcessFiles, IpCount))
                    {
                        //重写下一个执行步骤
                        ExecutionStep(ExecutionStepEnum.EarlyPeriod.Value().ToString());
                        var nextExecutionStatus = ExecutionStatusEnum.Start.Value().CToString();
                        ExecutionStatus(nextExecutionStatus);
                    }
                    else
                    {
                        Log.Debug("当前步骤:获取数据未满足升级要求");
                    }
                }
            }
            catch (Exception ex)
            {
                Log.ErrorFormat("获取基础数据就报错了:{0}",ex);
            }
        }

    }
}

模板的实现

/// <summary>
    /// Functional Description:通用上传文件模板
    /// Creater:ZhangQC
    /// Date:2018/4/12 16:27:36
    /// </summary>
    public class SccGetBaseDataTemplate : GetBaseDataTemplate
    {
        /// <summary>
        /// 基础类
        /// </summary>
        readonly BaseRoots _baseRoots;

        /// <summary>
        /// 预热数据适用
        /// </summary>
        private static bool _isRunForSystem = false;

        /// <summary>
        /// 预热数据适用
        /// </summary>
        private static bool _isRunForInterface = false;

        private readonly List<ConfiguredSupplierList> _configuredSupplierList;

        public SccGetBaseDataTemplate(BaseRoots baseRoots)
            : base(baseRoots)
        {
            //base.WriteLog();
            this._baseRoots = baseRoots;
            _configuredSupplierList = ConfiguredSupplier;
        }

        /// <summary>
        /// 处理接口数据
        /// </summary>
        private readonly IProcessExternalInterface _processInterfaceData = IocFactory.Resolve<IProcessExternalInterface>();

        /// <summary>
        /// function description:处理来自文件上传的数据
        /// creator:ZhangQC
        /// date:2019-3-29
        /// </summary>
        /// <returns></returns>
        protected override bool FromUpload()
        {
            try
            {
                var needProcessFiles = _baseRoots.GetContext().GetNeedProcessFile(j => j.OrgID == OrgId);
                if (needProcessFiles.Any())
                {
                    //循环组织结构
                    foreach (var needProcessFile in needProcessFiles)
                    {
                        IocFactory.Resolve<IProcessFromUpload>().ProcessExeclSaveToData(needProcessFile);
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                Log.ErrorFormat("从用户上传获取数据出错:{0}", ex);
                return false;
            }
        }

        /// <summary>
        /// function description:处理来自接口的数据
        /// creator:ZhangQC
        /// date:2019-3-29
        /// </summary>
        /// <returns></returns>
        protected override bool FromInterface()
        {
            try
            {
                return true;
            }
            catch (Exception ex)
            {
                Log.ErrorFormat("从系统获取数据初始化出错:{0}", ex);
                return false;
            }
        }

        /// <summary>
        /// 指标绩效计算需要的系统数据
        /// </summary>
        /// <returns></returns>
        protected override bool FromSystemData()
        {
            try
            {
                return true;
            }
            catch (Exception ex)
            {
                Log.ErrorFormat("从系统获取数据初始化出错:{0}", ex);
                return false;
            }
        }
    }

只要继承模板就可以实现每个客户每个步骤的不同实现了

下面我们来看加入策略模式后的代码

跟上面的是不同的步骤,但是意思是样的,就是把实现换成下面的差不多格式

   public class SccGetBaseDataTemplate : GetBaseDataTemplate
    {
        private readonly IRunStartegy _startegy;

        public CommonStep(IRunStartegy startegy)
        {
            this._startegy = startegy;
        }

        public override void WriteLog()
        {
            _startegy.LogStep();
        }

        protected override bool Run()
        {
            try
            {
                return this._startegy.Run();
            }
            catch (Exception ex)
            {
                Log.ErrorFormat("逻辑运算出错咯:{0}", ex);
                return false;
            }
        }
    }

下面就可以对相同客户实现不同的实现,只要实现的类继承IRunStartegy 此接口可以了

public class SccFrequency: StartegyBase, IRunStartegy
    {
        public bool Run()
        {
            using (var dbContext = new SMS_V40Context())
            {
                dosomething
            }
        }

        public void LogStep()
        {
            Log.Debug("进入频率计算步骤");
        }
    }

 

posted @ 2020-07-10 17:28  小小的菜鸟程序员  阅读(209)  评论(0编辑  收藏  举报