策略模式
定义(来自维基百科)
策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要交“个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。
特征
- 定义了一族算法(业务规则);
- 封装了每个算法;
- 该族的算法可以互相替换。
示例
// 计算奖金接口
interface ISalary
{
void Calc();
}
public class Level1Salary:ISalary
{
public static readonly int Level = 1;
public void Calc()
{
Console.WriteLine("等级1的奖金计算");
}
}
public class Level2Salary:ISalary
{
public static readonly int Level = 2;
public void Calc()
{
Console.WriteLine("等级2的奖金计算");
}
}
public class Level3Salary:ISalary
{
public static readonly int Level = 3;
public void Calc()
{
Console.WriteLine("等级3的奖金计算");
}
}
public Context
{
ISalary salaryStragegy;
public Context(ISalary salary)
{
this.salaryStragegy = salary;
}
public void Calc()
{
this.salaryStragegy.Calc();
}
}
// 消费场景
public class MainApp
{
public static void Main()
{
Context context;
context = new Context(new Level1Salary());
context.Calc();
context = new Context(new Level2Salary());
context.Calc();
context = new Context(new Level3Salary());
context.Calc();
//
foreach (var item in new List<int> {1, 2, 3})
{
CalcSalary(item);
}
}
// 稍微改进一下
public List<ISalary> LevelSalarys = new List<ISalary>{new Level1Salary(), new Level2Salary(), new Level3Salary()};
public void CalcSalary(int level)
{
var levelSalary = LevelSalarys.Find(l=>l.Level.equals(level));
new Context(levelSalary).Calc();
}
}
思考:如何通过MEF的方式对策略模式进行消费?
解决的问题
客户端(调用者)可以根据条件来选择不同的策略来解决不同的问题。
优点
- 由于策略类实现自同一个接口,策略类可以自由切换;
- 易于扩展,符合开闭原则(面向修改封闭,面向扩展开放),基本上可以在不改变原有代码的基础上进行扩展。
缺点
- 随着策略类的数量逐渐增多,维护各个策略类会给开发带来额外的开销;
- 必须对客户端暴露所有的策略类,因为使用哪种策略是由客户端决定的
适用的场景
- 几个类的主要逻辑相同,只在部分逻辑的算法和行为上稍有区别的情况。
- 有几种相似的行为,或者说算法,客户端需要动态地决定使用哪一种,那么可以使用策略模式,将这些算法封装起来供客户端调用。
总结
策略模式是一种简单常用的模式,我们在进行开发的时候,会经常有意无意地使用它,一般来说,策略模式不会单独使用,跟模版方法模式、工厂模式等混合使用的情况比较多。
本文完。