设计模式(二十二)—— 策略模式

模式简介


定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换。本模式使得算法可独立于使用它的客户而变化。

策略模式也被称为政策模式,它是一种行为型模式。为了完成某一项任务,往往可以有很多种不同的方式,例如商场促销,有不同的促销手段,比如提价50满100减20、原价两倍打八折等等,这每一种方式我们称之为策略。为了避免将策略硬编码在程序当中,可以使用策略模式,在系统运行过程中根据具体的环境或者条件执行不同的策略。

结构分析


UML类图

角色说明

  • Context

上下文类。包含一个对Strategy对象的引用,提供一个方法配置ConcreteStrategy对象,实现算法的动态替换。

  • Strategy

策略接口。定义算法的公共接口,Context类通过这个接口调用具体策略的算法。

  • ConcreteStrategy

具体策略。实现策略接口,定义具体算法。

工作原理

Context类提供一个方法(SetStrategy)设置具体算法,并将该对象的引用保存到私有变量_strategy中。Context将客户端请求转发给_strategy对象,完成策略调用。

结构代码

//策略接口
interface IStrategy
{
    void AlgorithmInterface();
}

//上下文类
class Context
{
    private IStrategy _strategy;
    public void SetStrategy(IStrategy strategy)
    {
        _strategy = strategy;
    }
    public void ContextInterface()
    {
        _strategy.AlgorithmInterface();
    }
}

//具体策略A
class ConcreteStrategyA : IStrategy
{
    public void AlgorithmInterface()
    {
        Console.WriteLine("Called ConcreteStrategyA.AlgorithmInterface()");
    }
}

//具体策略B
class ConcreteStrategyB : IStrategy
{
    public void AlgorithmInterface()
    {
        Console.WriteLine("Called ConcreteStrategyB.AlgorithmInterface()");
    }
}

//客户端调用
class Program
{
    static void Main(string[] args)
    {
        Context context = new Context();
        context.SetStrategy(new ConcreteStrategyA());
        context.ContextInterface();
        context.SetStrategy(new ConcreteStrategyB());
        context.ContextInterface();
        Console.ReadLine();
    }
}

程序输出:

示例分析


本节我们依然实现文章开头中的示例,首先声明ISalesPromotion接口。

public interface ISalesPromotion
{
    void Calculate(int orgPrice);
}

分别实现提价50满100减20以及原价两倍打八折两种销售策略。

public class Reduction : ISalesPromotion
{
    public void Calculate(int orgPrice)
    {
        var price = orgPrice + 50 - 20;
        Console.WriteLine($"Original Price : [{orgPrice}] , Price : [{price}]");
    }
}

public class Discount : ISalesPromotion
{
    public void Calculate(int orgPrice)
    {
        var price = orgPrice * 2 * 0.8;
        Console.WriteLine($"Original Price : [{orgPrice}] , Price : [{price}]");
    }
}

创建产品类

public class Product
{
    private ISalesPromotion _promotion;
    public void SetPromotion(ISalesPromotion promotion)
    {
        _promotion = promotion;
    }
    public void PrintPrice(int price)
    {
        _promotion.Calculate(price);
    }
}

客户端调用

class Program
{
    static void Main(string[] args)
    {
        int price1 = 120;
        Product p1 = new Product();
        //设置促销策略为满减
        p1.SetPromotion(new Reduction());
        p1.PrintPrice(price1);

        int price2 = 500;
        Product p2 = new Product();
        //设置促销策略为打折
        p2.SetPromotion(new Discount());
        p2.PrintPrice(price2);

        Console.ReadLine();
    }
}

程序输出

使用场景


  • 许多相关的类仅仅时行为上有差异。策略模式可以动态地让一个对象在众多行为中选择一种行为。

  • 一个系统需要动态地在几种算法中选择一种。
  • 一个对象有很多行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。
  • 不希望客户知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性及安全性。

posted @ 2018-07-23 20:59 Answer.Geng 阅读(...) 评论(...) 编辑 收藏