设计模式(二十二)—— 策略模式
模式简介
定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换。本模式使得算法可独立于使用它的客户而变化。
策略模式也被称为政策模式,它是一种行为型模式。为了完成某一项任务,往往可以有很多种不同的方式,例如商场促销,有不同的促销手段,比如提价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();
}
}
程序输出
使用场景
-
许多相关的类仅仅时行为上有差异。策略模式可以动态地让一个对象在众多行为中选择一种行为。
-
一个系统需要动态地在几种算法中选择一种。
-
一个对象有很多行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。
-
不希望客户知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性及安全性。