这里我们使用动态设定的方法来指定鸭子子类的行为,而不是在构造函数中通过实例化指定。
添加两个方法:
类图为:
代码为:
public void setFlyBehavior(FlyBehavior fb)
{
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb)
{
quackBehavior = qb;
}
添加一个Duck的子类ModelDuck类
类图为:
代码为:
class ModelDuck:Duck
{
public override void display()
{
Console.WriteLine("我显示为模型鸭");
}
}
测试类:
#region 测试红头鸭
Duck mld = new ModelDuck();
mld.display();
mld.setFlyBehavior(new FlyWithWings());
mld.performFly();
#endregion
此时,在运行时指定ModelDuck是可以飞的。
显示为:
此时,我需要一个不能飞的模型鸭,就不必修改ModelDuck类的代码,而只需修改一处代码
Duck mld = new ModelDuck();
mld.display();
mld.setFlyBehavior(new FlyNoWay());
mld.performFly();
#endregion
Console.ReadKey();
显示为:
到此,我们已经完善了整个程序的设计,使得程序的扩展性和重用性都更好.
总结一下:
(1)将常常会产生需求变动的方法,抽象为接口,然后有一组行为类去实现,而不是由其子类去实现(实现代码的重用性)
(2)在超类中,声明共有的字段,其类型为刚刚抽象的接口类型
(3)在子类中的构造函数中,根据需要,将行为类实例的引用赋给刚刚声明的共有字段,此时确定子类所具有的具体行为(实现代码的灵活性)
(4)替代(3)在超类中,针对每类行为提供一个方法,使得在运行时确定子类所具有的具体行为(最大化代码的灵活性)
其实,这本身就是策略模式的应用场合.