策略模式:它定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
例:如何去设计一个Duck类,以及多样的继承与Duck类的子类呢?Duck有以下行为:swim(),fly(),display(),quack()。
1.首先思考一下,如果按照自己以往的习惯会怎么去设计呢?
定义一个Duck类,然后里面定义上述三个方法,所有继承与Duck类的子类都会包含这三个方法,我们可以去重写这三个方法,使子类可以拥有自己的变化。那么问题来了,假如,我有一只橡皮鸭,我不应该让它有飞的行为,我该怎么办呢?
2.利用重写呢?
那么是不是,每出现一个新的子类的时候,我们就要手动的对父类里的方法进行重写呢?这样的话,我们的代码一点复用性都不存在了,每次都要去重写一次。
3.利用接口怎么样?
好,我们把Duck的共同行为(不可变行为),与可改变行为分开,把fly()与quack()这两个方法做成接口,然后会飞的就去实现fly接口,会叫得就去实现quack接口。但是我们每次去继承某个接口的时候,我们就必须去手动实现接口里面的方法,还是要不断的写代码。
4.接下来应该怎么做
既然,我们都已经把Duck的可变与不可变行为分开了,那就分的彻底一些,把Fly与Quack专门做成两个行为类FlyBehavior与QuackBehavior,远离Duck类。不同的fly的方式都单独做成一个个类,这些类继承FlyBehavior父类。Quack也一样。例如,FlyWithWind继承与FlyBehavior。
5.如何把这些连接到一起?
我们在Duck类中,写上FlyBehavior flyBehavior和QuackBehavior quackBehavior两个字段,这两个字段。所有继承于Duck的子类都会有这两个字段,并在各自的构造方法中进行字段赋值,例如:flyBehavior = new FlyWithWing(); 利用重写。这样,子类就相当于把飞行行为委托给了FlyWithWing类。
6.好处是什么?
只要我们写好了FlyBehavior与QuackBehavior以及他们的子类,我们就可以让他们帮助任何需要此行为的对象进行该行为。当对象以及代码非常多的时候,这样的模式使代码更容易拓展以及维护。
7.接口的隐式实现还可以进行优化:
把两个行为基类做成接口,然后Duck中两个字段定义成接口类型,然后通过 IFlyBehavior flyB = (IFlybehavior)new FlyWithWind()这样隐式实现接口中的方法。省去了不断的实例化类对象的过程。
下面为最终的模式写上这个示例的代码:
<p>/// <summary>
/// 策略模式Duck示例
/// </summary>
using System;
namespace StrategyPattern
{
// Duck超类
public abstract class Duck
{
// 两个可变行为的字段以及属性
public IFlyBehvior flyBehavior;
public IQuack quackBehavior;
// 两个共有行为
public void Swim()
{
Console.WriteLine ("I'm swimming");
}
public abstract void Display ();
}
// 继承与Duck的类 橡皮玩具鸭
public class ToyDuck : Duck
{
#region implemented abstract members of Duck
public override void Display ()
{
Console.WriteLine ("I'm ToyDuck");
}
#endregion
// 构造器里对继承来的接口对象进行初始化。
public ToyDuck()
{
flyBehavior = (IFlyBehvior)new FlyNoWay ();
quackBehavior = (IQuack)new GuaGuaJiao ();
}
}
// 两个行为接口,以及继承这些接口的行为类
public interface IFlyBehvior
{
void Fly ();
}
public interface IQuack
{
void Quack ();
}
public class FlyWithWind : IFlyBehvior
{
#region IFlyBehvior implementation
void IFlyBehvior.Fly ()
{
Console.WriteLine ("I'm fly With Wind");
}
#endregion
}
public class FlyNoWay : IFlyBehvior
{
#region IFlyBehvior implementation
void IFlyBehvior.Fly ()
{
Console.WriteLine ("I can't fly");
}
#endregion
}
public class GuaGuaJiao : IQuack
{
#region IQuack implementation
void IQuack.Quack ()
{
Console.WriteLine ("gua gua");
}
#endregion
}
public class NoQuack : IQuack
{
#region IQuack implementation
void IQuack.Quack ()
{
Console.WriteLine ("I can't quack");
}
#endregion
}
class MainClass
{
public static void Main (string[] args)
{
// 调用橡皮玩具鸭的fly方法与quack方法
ToyDuck td = new ToyDuck ();
td.flyBehavior.Fly ();
td.quackBehavior.Quack ();
}
}
}<span style="font-size:14px;">
</span></p>