zoukankan      html  css  js  c++  java
  • 软件设计模式之策略模式(Strategy) 壹

    策略模式

    描述

    它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化不会影响到使用算法的客户。

    优点

    策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。  

    策略模式的Strategy类为Context定义了很多可重用的算法,继承可以让你更好地析取出算法中的公共功能,同时简化了单元测试,因为每个算法都是单独的类,都可以通过自己单独的接口进行测试。

    简而言之呢就是策略封装了算法会有的变化

    实现

        /*
         策略模式
         */
    
        /// <summary>
        /// 策略模式抽象算法类
        /// </summary>
        abstract class Strategy
        {
            public abstract void AlgorithmInterface();
    
        }
    
        /// <summary>
        /// 策略模式实现类A
        /// </summary>
        class ConcreteStrategyA : Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("算法A实现");
            }
        }
    
        /// <summary>
        /// 策略模式实现类B
        /// </summary>
        class ConcreteStrategyB : Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("算法B实现");
            }
        }
    
        /// <summary>
        /// 策略模式实现类C
        /// </summary>
        class ConcreteStrategyC : Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("算法C实现");
            }
        }
    
        /// <summary>
        /// 上下文接口
        /// </summary>
        class Context
        {
            Strategy _strategy;
            /// <summary>
            /// 初始化时传入策略对象
            /// </summary>
            /// <param name="strategy"></param>
            public Context(Strategy strategy)
            {
                _strategy = strategy;
            }
    
            /// <summary>
            /// 调用算法
            /// </summary>
            public void ContextInterface()
            {
                _strategy.AlgorithmInterface();
            }
        }
    

    与简单工厂差别

    工厂模式是创建型模式,适应对象的变化。
    策略模式是行为性模式,适应行为的变化。

    策略模式、简单工厂适用场景

    我认为工厂模式适合的场景是不复杂的,比较具体的,比如文具:铅笔、尺子、橡皮;

    策略模式则是适用于算法的,比如商场折扣:买200反20,买300反30;

    简单工厂+策略模式的使用

    策略模式封装了算法,但是实际使用中不可避免的会用到switch,策略模式+简单工厂的模式就可以将条件判断封装起来,避免了在界面层做过多的条件判断。

    操作类实现:还是使用策略模式的实现

        /// <summary>
        /// 策略模式抽象算法类
        /// </summary>
        abstract class Strategy
        {
            public abstract void AlgorithmInterface();
    
        }
    
        /// <summary>
        /// 策略模式实现类A
        /// </summary>
        class ConcreteStrategyA : Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("算法A实现");
            }
        }
    
        /// <summary>
        /// 策略模式实现类B
        /// </summary>
        class ConcreteStrategyB : Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("算法B实现");
            }
        }
    

      然后上下文跟策略模式有所不同,上下文加入简单工厂的思想

    /// <summary>
        /// 简单工厂+策略模式
        /// </summary>
        class FactoryContext
        {
            Strategy _strategy;
            /// <summary>
            /// 工厂生成
            /// </summary>
            /// <param name="type"></param>
            public FactoryContext(string type)
            {
                switch (type)
                {
                    case "A":
                        _strategy = new ConcreteStrategyA();
                        break;
                    case "B":
                        _strategy = new ConcreteStrategyB();
                        break;
                    case "C":
                        _strategy = new ConcreteStrategyC();
                        break;
                }
            }
    
            /// <summary>
            /// 调用算法
            /// </summary>
            public void ContextInterface()
            {
                _strategy.AlgorithmInterface();
            }
        }
    

      反射

    策略模式+简单工厂,也只是把条件判断封装了起来而已,那可不可能不用switch了呢?可以,那就需要用到反射,“反射,反射,程序员的快乐”

    实现

    首先我们编写标识类,标识类使用Attribute类来做我觉得会好一点

        public class ReflectAttribute : Attribute
        {
            public string Tag { get; set; }
            public ReflectAttribute(string tag)
            {
                Tag = tag;
            }
        }
    

     然后我们给实现类打上标识

        /// <summary>
        /// 策略模式实现类A
        /// </summary>
        [ReflectAttribute("A")]
        class ConcreteStrategyA : Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("算法A实现");
            }
        }
    
        /// <summary>
        /// 策略模式实现类B
        /// </summary>
        [ReflectAttribute("B")]
        class ConcreteStrategyB : Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("算法B实现");
            }
        }
    
        /// <summary>
        /// 策略模式实现类C
        /// </summary>
        [ReflectAttribute("C")]
        class ConcreteStrategyC : Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("算法C实现");
            }
        }
    

     最后改造上下文

        /// <summary>
        /// 反射实现工厂+策略模式
        /// </summary>
        class ReflectContext
        {
            Strategy _strategy;
            public ReflectContext(string type)
            {
                Type abjType = typeof(Strategy);
                Assembly assem = abjType.Assembly;
                foreach (Type item in assem.GetTypes())
                {
                    if (item.IsClass && !item.IsAbstract && item.IsSubclassOf(abjType))
                    {
                        if (item.GetCustomAttribute<ReflectAttribute>().Tag == type)
                        {
                            _strategy = Activator.CreateInstance(item) as Strategy;
                        }
                    }
                }
            }
    
            public void ContextInterface()
            {
                
                _strategy.AlgorithmInterface();
            }
        }
    

      使用反射来优化策略模式就完成了。同时反射这种使用也可以用在需要写很多case的情况下,日常工作中经常会遇到,那么我觉得可以用一个类去封装switch中case的执行语句,然后每个执行方法打上标识,然后用反射去找到每个方法,这样代码看起来会舒服很多,而不是几百个case杵在那,里面还有无数行实现,看着头都大。

  • 相关阅读:
    Core Animation笔记(变换)
    Core Animation笔记(- Layer 基本属性)
    使用AndroidStudio编写APICloud模块需要注意的地方,解决模块未定义。
    MAC中使用APICloud同步代码错误解决办法
    【深入理解Java虚拟机 】类加载器的命名空间以及类的卸载
    【深入理解Java虚拟机 】类的加载器
    【深入理解Java虚拟机】类的初始化过程
    Netty中ByteBuf的引用计数线程安全的实现原理
    Java使用PipedStream管道流通信
    Java中的守护线程
  • 原文地址:https://www.cnblogs.com/zhoulei0517/p/15801498.html
Copyright © 2011-2022 走看看