设计模式之一:策略模式(Strategy Pattern)
在介绍策略模式之前先说下两个设计原则:
1. Identify the aspects of your application that vary and separate them from what stays the same.找到系统中变化的部分,将变化的部分同其它稳定的部分隔开。
2. Program to an interface, not an implementation.面向接口编程,而不要面向实现编程。
那什么是策略模式呢?
The Strategy Pattern defines a family of algorithms ,encapsulates each one , and makes them interchangeable. Strategy lets the algorithms vary independently from clients that use it.什么意思呢?就是说策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以互相替换。策略模式让算法独立于使用它的客户而独立变化。
举个例子:假设我们现在要为联想公司做个计算公司员工工资的计算器,我们知道联想是个国际化公司,在中国和美国都有员工,由于两个劳动力成本是不一样的,因此美国员工的工资和中国员工的工资工资计算方式是不一样的。我们可以把计算中国员工工资和计算美国员工工资视作两个独立的部分。类图如下:
具体实现:
//首先声明一个计算工资的接口
public interface ISalary
{
double CalculateSalary();
}
//中国员工工资的计算方式实现
public class ChineseSalary:ISalary
{
//基本工资
private readonly const double BASE_SALARY = 2000;
//奖金
private readonly const double BONUS = 2000;
public double CalculateSalary()
{
double totalSalary = BASE_SALARY + BONUS;
double tax = totalSalary * 0.2;
double salary = totalSalary - tax;
return salary;
}
}
//美国员工工资的计算方式实现
public class AmericanSalary : ISalary
{
//基本工资
private readonly const double BASE_SALARY = 8000;
//奖金
private readonly const double BONUS = 8000;
public double CalculateSalary()
{
double totalSalary = BASE_SALARY + BONUS;
double tax = totalSalary * 0.4;
double salary = totalSalary - tax;
return salary;
}
}
public class Calculator
{
private ISalary salary;
public Calculator(ISalary salary)
{
this.salary = salary;
}
public double GetSalary()
{
return this.salary.CalculateSalary();
}
}
应用场景
对应Strategy模式来说,主要有这些应用场景:
1. 多个类只区别在表现行为不同,可以用Strategy模式,在运行时动态选择具体要执行的行为。
2.需要在不同情况下使用不同的策略,或者策略还可能在未来使用其它方式实现。
3.对客户隐藏具体策略(算法)的实现细节,彼此完全独立。
优点:
1. 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用),还比继承更灵活,因为算法是独立的,可以灵活扩展。
2. 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3. 遵守大部分GRASP原则和常用设计原则,高内聚,低耦合。
缺点:
1.因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。