• 探讨跨客户业务处理模式


    背景

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

    缺点分析

    随着客户的增加以及每个客户的处理越来越个性化,原来服务设计已经补满足。此服务一共分为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("进入频率计算步骤");
            }
        }
  • 相关阅读:
    模仿JavaAppArguments.java示例,编写一个程序,此程序从命令行接收多个数 字,求和之后输出结果,写出其的设计思想、程序流程图、源程序代码。
    大道至简第二章读后感
    大道至简第一章读后感
    md5实现
    jdk-动态代理
    使用反射复制对象
    java-二分查找法
    java-base64
    cxf框架使用(一)
    Freemarket学习笔记(一)
  • 原文地址:https://www.cnblogs.com/creater/p/13280275.html
Copyright © 2020-2023  润新知