定义
策略模式定义了算法簇,分别把它们封装起来,让他们之间可以相互转化(应为同一算法簇的算法继承了同意抽象类或实现了同一个接口),此模式让算法的变化独立于使用算法的客户。
案例示意图
在这里一《Head First》的鸭子案例为例:
- 红色区域和蓝色区域都属于算法簇,而且同种颜色之间的算法可以互相替换。例如以蓝色为例,Quack和Squeak都实现了QuackBehaviour接口,都可以赋给Duck中的quck遍历。
算法优点
- 策略类之间可以方便的替换,因为都实现于同一个抽象。例如Duck中的fly对象,可以将FlyWithWings或FlyNoWay赋值给它。
- 可以很方便的扩充而不影响其他策略类,例如可以很方便的让某个类实现FlyBehaviour接口,而扩充算法簇
- 避免了if..else 和 switch那样的判断语句
- 面向接口编程,而不是面向实现编程,既也可以实现代码复用,也避免了继承带来的冗余烦恼
算法缺点
- 策略类过多,很难维护
- 必须将所有的实现方式暴露给使用者,以方便使用者使用,这就破环了面向对象的封装原则,而且使用者要明白算法的区别才能更好的使用。
代码实现
namespace Algorithm.Design
{
class Strategy
{
static void Main()
{
RedDuck redDuck = new RedDuck();
redDuck.SetFly(new FlyNoWay()); //先设置一种策略
redDuck.DoFlay();
redDuck.SetFly(new FlyWithWings());//更换策略
redDuck.DoFlay();
redDuck.Display();
}
}
public interface FlyBehaviour
{
void Fly();
}
public interface QuackBehaviour
{
void Quack();
}
public class Duck
{
FlyBehaviour Fly;
QuackBehaviour OneQuack;
public virtual void Display() { }
public void SetFly(FlyBehaviour fly)
{
this.Fly = fly;
}
public void SetQuack(QuackBehaviour quack)
{
this.OneQuack = quack;
}
public void DoFlay()
{
Fly?.Fly();
}
public void DoQuack()
{
OneQuack?.Quack();
}
}
public class RedDuck:Duck
{
public override void Display()
{
Console.WriteLine(" red duck");
}
}
public class RubberDuck : Duck
{
public override void Display()
{
Console.WriteLine(" rubber duck");
}
}
public class FlyWithWings : FlyBehaviour
{
public void Fly()
{
Console.WriteLine("fly with wings");
}
}
public class FlyNoWay : FlyBehaviour
{
public void Fly()
{
Console.WriteLine("fly no way");
}
}
public class Quack : QuackBehaviour
{
void QuackBehaviour.Quack()
{
Console.WriteLine("quack");
}
}
public class Squeak : QuackBehaviour
{
void QuackBehaviour.Quack()
{
Console.WriteLine("Squeak");
}
}
}