动态设定行为
①、在Duck类中,加入两个新方法。从此以后,我们可以调用这个方法改变鸭子的行为。
// 动态设定行为
public void setFlyBehavior(FlyBehavior fb){
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb){
quackBehavior = qb;
}
②、制造一个新的鸭子类型:模型鸭(ModelDuck.java)
// 模型鸭
public class ModelDuck extends Duck{
public ModelDuck(){
// 开始时,模型鸭不会飞
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("I'm a model duck");
}
}
③、建立一个新的FlyBehavior类型(FlyRocketPower.java)
// 火箭动力飞行
public class FlyRocketPower implements FlyBehavior{
@Override
public void fly() {
System.out.println("I'm flying with a rocket");
}
}
④、改变测试类(DuckSimulator.java),加上模型鸭,并使模型鸭具有火箭动力。
public class DuckSimulator{
public static void main(String[] args){
Duck mallard = new MallardDuck();
mallard.performFly();
mallard.performQuack();
// 动态绑定行为测试
System.out.println("动态绑定行为测试:");
Duck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPower());
model.performFly();
}
}
结果:
I'm flying
Quack
动态绑定行为测试:
I can't fly
I'm flying with a rocket
封装行为的全局观
描述事情方式稍有改变,不再把鸭子的行为说成是“一组行为”,开始把行为想成是多种(计算)策略。
策略代表鸭子能做的事(不同的叫法和飞法),这样的做法也能容易地用于用一群类计算不同超市(销售策略各异)的销售金额情况。
“有一个”可能比“是一个”更好
图中包含3种关系——IS-A(是一个)、HAS-A(有一个)、IMPLEMENTS(实现),能分清吗?
“有一个”关系的优势:每一鸭子都有一个FlyBchavior和
一个Quackachavior,好将飞行和呱呱叫委托给它们代为处
理。
当构成“有一个”关系时,如同本例一般,这就是组
合(composition)。这种做法和“继承”不同的地方在于
鸭子的行为不是继承来的,而是和适当的行为对象“组
合”来的。
这是一个很重要的技巧。也是我们使用的第三个设计原则:多用组合,少川继承。