策略模式(Strategy Pattern)

策略模式(Strategy Pattern)
策略模式定义了一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
别名:Policy(方针)
结构:

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

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

    class ConcreteStrategyA : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("Algorithm A implementation");
        }
    }

    class ConcreteStrategyB : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("Algorithm B implementation");
        }
    }

    class ConcreteStrategyC : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("Algorithm C implementation");
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyStrategy
{
    class Context
    {
        private Strategy strategy;

        public Context(Strategy strategy)
        {
            this.strategy = strategy;
        }

        public void ContextInterface()
        {
            strategy.AlgorithmInterface();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyStrategy
{
    class Program
    {
        static void Main(string[] args)
        {
            Context context;

            context = new Context(new ConcreteStrategyA());
            context.ContextInterface();

            context = new Context(new ConcreteStrategyB());
            context.ContextInterface();

            context = new Context(new ConcreteStrategyC());
            context.ContextInterface();

            Console.ReadKey();
        }
    }
}

参与者:
 Strategy( 策略 )
— 定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。
• ConcreteStrategy(具体策略)
— 以Strategy接口实现某具体算法。
• Context(上下文)
— 用一个ConcreteStrategy对象来配置。
维护一个对Strategy对象的引用。
— 可定义一个接口来让Strategy访问它的数据。

效果:
1)相关算法系列Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。
2) 一个替代继承的方法。继承提供了另一种支持多种算法或行为的方法。你可以直接生成一个Context类的子类,从而给它以不同的行为。但这会将行为硬行编制到 Context中,而将算法的实现与Context的实现混合起来 , 从而使Context难以理解、难以维护和难以扩展,而且还不能动态地改变算法。最后你得到一堆相关的类 ,  它们之间的唯一差别是它们所使用的算法或行为。将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展。
3) 消除了一些条件语句。Strategy模式提供了用条件语句选择所需的行为以外的另一种选择。当不同的行为堆砌在一个类中时 ,  很难避免使用条件语句来选择合适的行为。将行为封装在一个个独立的Strategy类中消除了这些条件语句。

实现:
1)定义Strategy和Context接口

一种办法是让Context将数据放在参数中传递给Strategy操作——也就是说, 将数据发送给Strategy。这使得Strategy和Context解耦。另一种办法是让Context将自身作为一个参数传递给Strategy, 该Strategy再显式地向该Context请求数据。或者,Strategy可以存储对它的Context的一个引用, 这样根本不再需要传递任何东西。

2)将Strategy作为模板参数

template <class AStrategy>
class Context 
{
public
    void Operation()
    {
        theStrategy.DoAlgorithm();
    }
private:
    AStrategy theStrategy;
}

class MyStrategy
{
public:
    void DoAlgorithm();
}

Context<MyStrategy> myContext;
可以在编译时选择Strategy,不需要在运行时改变,提高效率。

3)使Strategy对象称为可选

实际应用代码:

商场购物结账,根据不同的付账方式,选择不同的计算策略。CashContext用到了简单工厂,下面代码中策略模式与简单工厂相结合,降低了代码的耦合性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyStrategy1
{
    abstract class CashSuper
    {
        public abstract double acceptCash(double money);
    }

    class  CashNormal : CashSuper
    {
        public override double acceptCash(double money)
        {
            return money;
        }
    }

    class CashRebate : CashSuper
    {
        private double moneyRebate = 1d;
        public CashRebate(string moneyRebate)
        {
            this.moneyRebate = double.Parse(moneyRebate);
        }

        public override double acceptCash(double money)
        {
            return money * moneyRebate;
        }
    }

    class CashReturn : CashSuper
    {
        private double moneyCondition = 0.0d;
        private double moneyReturn = 0.0d;
        public CashReturn(string moneyCondition, string moneyReturn)
        {
            this.moneyCondition = double.Parse(moneyCondition);
            this.moneyReturn = double.Parse(moneyReturn);
        }

        public override double acceptCash(double money)
        {
            double result = money;
            if (money >= moneyCondition)
            {
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;
            }

            return result;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyStrategy1
{
    class CashContext
    {
        CashSuper cs = null;

        public CashContext(string type)
        {
            switch (type)
            {
                case "正常收费":
                    CashNormal cs0 = new CashNormal();
                    cs = cs0;
                    break;
                case "满300返100":
                    CashReturn cr1 = new CashReturn("300", "100");
                    cs = cr1;
                    break;
                case "打8折":
                    CashRebate cr2 = new CashRebate("0.8");
                    cs = cr2;
                    break;
            }
        }

        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyStrategy1
{
    class Program
    {
        static void Main(string[] args)
        {
            double totalPrices = 100d;
            string cashType = "打8折";        

            CashContext csuper = new CashContext(cashType);
            totalPrices = csuper.GetResult(totalPrices);

            Console.ReadKey();
        }
    }
}

参考《设计模式》、《大话设计模式》,进行整理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值