C# 反射 策略模式改造 switch case 或者 if else

一、前言

        由于在业务处理上使用了较多的 switch case 或者 if else,使用了策略模式改造下代码,以便后续的扩展,

不应为了设计模式而设计模式,应从具体业务出发,不然只会让代码的复杂度增加

二、何为策略模式

         也叫 政策模式(Policy Pattern)。指的是对象具备某个行为,但是在不同的场景中,该行为有不同的实现算法。比如一个人的交税比率与他的工资有关,不同的工资水平对应不同的税率。

策略模式使用的就是面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。

策略模式本质:分离算法,选择实现

三、应用策略模式

1)直白写法

public void DoWork(int taskType)
        {
            switch (taskType)
            {
                case (int)TaskType.上传单价:
                    Console.WriteLine("执行上传单价业务");
                    break;
                case (int)TaskType.上传工单:
                    Console.WriteLine("执行上传工单业务");
                    break;
                case (int)TaskType.上传配件:
                    Console.WriteLine("执行上传配件业务");
                    break;
                case (int)TaskType.上传附件:
                    Console.WriteLine("执行上传附件业务");
                    break;
                default:
                    Console.WriteLine("无效任务类型");
                    break;
            }
        }

 2)简单策略模式

截取自  http://my.oschina.net/BreathL/blog/52655

2.1)创建策略接口类

/// <summary>
    /// 策略类接口
    /// </summary>
    public interface IStrategy
    {
        void DoStrategyWork();
    }

2.2)创建策略实现类

public class 上传单价 : IStrategy
    {
        public void DoStrategyWork()
        {
            Console.WriteLine("执行上传单价业务");
        }
    }

2.3)创建对外调用类

扫描二维码关注公众号,回复: 13596504 查看本文章
public class User
    {
        public void StartHere(IStrategy strategy)
        {
            strategy.DoStrategyWork();
        }
    }

2.4)调用

new 一般策略写法.User().StartHere(new InstanceFactory<一般策略写法.IStrategy>().CreateInstanceByEnumName(tType));

3)上下文的引入

上下层调用、交互,往往不是固定不变的,比如调用函数的参数变化、增加方法等

截取自  http://my.oschina.net/BreathL/blog/52655

3.1)创建策略抽象类(接口也是可以的,具体业务具体分析)

/// <summary>
    /// 策略类抽象类
    /// </summary>
    public abstract class IStrategy
    {
        public abstract TaskType CommandType { get; }

        public abstract void DoStrategyWork(StrategyContext strategyContext);
    }

3.2)创建策略实现类

public class 上传单价 : IStrategy
    {
        public override TaskType CommandType => TaskType.上传单价;

        public override void DoStrategyWork(StrategyContext strategyContext)
        {
            Console.Write("执行上传单价业务 ");
            Console.WriteLine("我是可变参数:" + strategyContext.pars);
        }
    }

3.3)创建上下文类

通过上下文  进行对应策略算法调用,执行具体实现类的算法,同时写携带业务交互参数

public class StrategyContext
    {
        private IStrategy _strategy;

        #region 可变的上下文参数

        public string pars { get; set; }

        #endregion

        public StrategyContext(IStrategy strategy)
        {
            this._strategy = strategy;
        }

        public void InvokingStrategy()
        {
            this._strategy.DoStrategyWork(this);
        }
    }

3.4)创建对外调用类

public class User
    {
        private StrategyContext strategyContext;

        public User(TaskType taskType, string pars)
        {
            this.strategyContext = new StrategyContext(new InstanceFactory<IStrategy>().CreateInstanceBySubClass(taskType));
            this.strategyContext.pars = pars;
        }

        public void StartHere()
        {
            strategyContext.InvokingStrategy();
        }
    }

3.5)调用

new 上下文策略写法.User(tType, "我是参数").StartHere();

四、反射创建对象

/// <summary>
    /// 利用反射创建具体策略类,并缓存起来
    /// </summary>
    public class InstanceFactory<T> where T : class
    {
        /// <summary>
        /// 一般处理对象缓存
        /// </summary>
        private static Dictionary<TaskType, T> dicCommands = new Dictionary<TaskType, T>();

        /// <summary>
        /// 上下文策略对象缓存
        /// </summary>
        private static Dictionary<TaskType, T> dicContextCommands = new Dictionary<TaskType, T>();
        
        /// <summary>
        /// 根据TaskType 的名称创建类对象
        /// </summary>
        /// <param name="taskType"></param>
        /// <returns></returns>
        public T CreateInstanceByEnumName(TaskType taskType)
        {
            foreach (TaskType cd in Enum.GetValues(typeof(TaskType)))
            {
                if (!dicCommands.Keys.Contains(cd))
                {
                    //(基类)Assembly.Load("当前程序集名称").CreateInstance("命名空间.子类名称"));  
                    T baseCommand = Assembly.Load(typeof(T).Assembly.GetName().Name)
                        .CreateInstance((typeof(T).Namespace + "." + cd)) as T;

                    if (baseCommand != null)
                    {
                        dicCommands.Add(cd, baseCommand);
                    }
                }

            }

            return dicCommands.FirstOrDefault(c => c.Key == taskType).Value;
        }

        /// <summary>
        /// 通过继承关系创建子类
        /// </summary>
        /// <param name="taskType"></param>
        /// <returns></returns>
        public T CreateInstanceBySubClass(TaskType taskType)
        {
            Type objType = typeof(T);
            // 获取此类型所在的程序集
            Assembly assembly = objType.Assembly;
            // 遍历获取此程序集中所有的类
            foreach (Type t in assembly.GetTypes())
            {
                // 是类并且不是抽象类并且继承IBaseCommand
                if (t.IsClass && !t.IsAbstract && t.IsSubclassOf(objType))
                {
                    // 创建策略实例类
                    T command = Activator.CreateInstance(t) as T;

                    var key = (TaskType)Enum.Parse(typeof(TaskType), t.GetProperty("CommandType").DeclaringType.Name);

                    if (command != null && !dicCommands.ContainsKey(key))
                    {
                        dicContextCommands.Add(key, command);
                    }
                }
            }

            return dicContextCommands.FirstOrDefault(c => c.Key == taskType).Value;
        }
    }

五、代码下载

https://github.com/harrylsp/Strategy

六、参考引用

https://my.oschina.net/BreathL/blog/52655

https://blog.csdn.net/qq_19348391/article/details/84404034

https://blog.csdn.net/site008/article/details/77947566

猜你喜欢

转载自blog.csdn.net/qq1326702940/article/details/88407103