zoukankan      html  css  js  c++  java
  • 设计模式之策略模式

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

    策略模式的例子使用商场收银再好不过了,商场默认为正常收银;如果有打折,比如是打8折;如果有满减,满100减20;再或者满100送10积分;也可能是打折后满200减20等等这样的很多方式。而这些一个个方式也就是一个个不同的算法,根据策略模式的定义,将这些一个个算法分别封装起来(即有自己的一个个类),然后客户端想怎么用就怎么用。

    策略模式三元素:1.Context上下文,用一个属性或者是一个方法来配置,维护一个策略的对象;

            2.策略类(策略接口),定义所有支持算法的接口;

            3.具体策略类,实现了各自具体的算法,继承自策略类(策略接口)。

    上下文对象类:

        class StrategyContext
        {
            Strategy strategy;
            public StrategyContext(Strategy strategy)
            {
                this.strategy = strategy;
            }
    
            public void ContextInterface()
            {
                strategy.AlgorithmInterface();
            }
        }

    策略类:

       abstract class Strategy
        {
           public abstract void AlgorithmInterface();
        }

    策略实现类:

        class StrategyA:Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("我是算法A");
            }
        }
    
        class StrategyB:Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("我是算法B");
            }
        }
    
        class StrategyC:Strategy
        {
            public override void AlgorithmInterface()
            {
                Console.WriteLine("我是算法C");
            }
        }

    代码都是比较简单的,上下文对象中一个策略抽象类的对象,在构造函数中进行赋值,一个执行策略行为的方法;策略类,只有一个抽象的方法(根据自己的需求可以添加各种方法);策略实现类,和策略类没大差,就是实现了具体的方法。

    调用:

                StrategyContext context = new StrategyContext(new StrategyA());
                context.ContextInterface();
    
                context = new StrategyContext(new StrategyB());
                context.ContextInterface();
    
                context = new StrategyContext(new StrategyC());
                context.ContextInterface();

    看到调用是不是想破口大骂呢,什么破模式,我还不是实例了具体的策略吗,干吗还要传递给上下文对象,最后还不是执行了我策略的方法呢,这里的确是存在问题,不过骚等待我修改。

    修改上下文对象类:

     public StrategyContext(string strategyType)
            {
                switch (strategyType)
                {
                    case "StrategyA":
                        strategy = new StrategyA();
                        break;
                    case "StrategyB":
                        strategy = new StrategyB();
                        break;
                    case "StrategyC":
                        strategy = new StrategyC();
                        break;
                    default:
                        break;
                }
            }

    通过添加了构造参数,然后在内部判断到底实例哪一个策略。

    调用:

               StrategyContext context = new StrategyContext("StrategyA");
                context.ContextInterface();
    
                context = new StrategyContext("StrategyB");
                context.ContextInterface();
    
                context = new StrategyContext("StrategyC");
                context.ContextInterface();

    调用也很简洁,聪明的你是不是发现,怎么有点简单工厂的影子呢,没错,这个简单工厂还真是无处不在呢。

    这样只后,如果有新的策略出现,只需添加一个策略类,然后修改下上下文对象中的判断即可。如果亲爱的你不想这么做,没关系,你可以使用反射的方式来创建这个策略类哦,具体不再赘述,可以参考本人的另外一个 抽象工厂模式的文章有介绍。

    后记(分析):

    通过上述的例子我们可以看到,策略模式是一种定义了一系列算法的方法,从概念上来说所有这些类的算法完成的都是相同的工作,只是实现不同而已,它是以相同的方式调用所有的算法(当然前提是策略对象不同哦),减少了各种算法与使用算法类之间的耦合。策略模式的Strategy类为Context定义了一系列的算法或者行为,继承有助于提取出这些算法中的公共功能。策略模式就是用来封装算法的,但是在实践中,我们可以用它来封装几乎任何类型的规则,只要分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。

    好了,本次模式介绍就结束了,欢迎大家提意见和建议。

  • 相关阅读:
    luogu1131 [ZJOI2007]时态同步
    luogu1879 [USACO06NOV]玉米田Corn Fields
    luogu1345 [USACO5.4]奶牛的电信Telecowmunication
    luogu2463 [SDOI2008]Sandy的卡片
    spoj694 DISUBSTR
    luogu2852 [USACO06DEC]牛奶模式Milk Patterns
    poj2217 Secretary 后缀数组
    luogu3809 后缀排序 后缀数组
    hdu4405 Aeroplane chess
    poj2096 Collecting Bugs
  • 原文地址:https://www.cnblogs.com/ListenFly/p/3220754.html
Copyright © 2011-2022 走看看