整合在于,鸭子现在会将飞行和呱呱叫的动作“委托”别人处理,而不是使用定义在Duck类(或子类)内的呱呱叫和飞行方法。
做法是这样的:
1.首先,在Duck类中加入两个“实例变量”,分别为"flyBehavior"与"quackBehavior",声明为接口类型(而不是具体类实现类型),每个鸭子对象都会动态地设置这些变量以在运行时引用正确的行为类型(例如:FlyWithWings,Squeak等)。
我们也必须将Duck类与其所有子类中的fly()和quakc()删除,因为这些行为已经被搬到FlyBehavior与quackBehavior中了。
我们用两个相似的方法performFly()和performQuack()取代Duck类中flyBehavior()和quackBehavior()
2.现在我们来实现performQuack():
public abstract class Duck {
//飞行行为
protected FlyBehavior flyBehavior;
//鸭子叫行为
protected QuackBehavior quackBehavior;
public Duck() {
}
}
在这部分代码中,我们不在乎quackBehavior接口的对象到底是什么,我们只关心该对象知道如何进行呱呱叫就够了。
3.好吧,现在来关心“如何设定flyBehavior与quackBehavior的实例变量”看看mallardDuck类:
public class MallardDuck extends Duck {
public MallardDuck() {
//定义叫的行为:有叫声
quackBehavior = new Quack();//绿头鸭使用quack类处理呱呱叫,所以当performQuack()被调用时,叫的职责托付给了Quack()对象,得到了呱呱叫
//定义飞的行为:能飞
flyBehavior = new FlyWithWings();//使用FlyWithWings()作为其flyBehavior行为
}
@Override
public void display(){
System.out.println("i'm a real Mallard duck");
}
}
因为MallardDuck继承Duck类,所以具有flyBehavior和quackBehavior变量。当MallardDuck实例化时,他的构造器会把继承来的quackBehavior实例变量初始化成Quack类型的新实例(Quack是QuackBehavior的具体实现类)。
同样方法也可以用在飞行行为上。
测试Duck代码
1.输入并编译下面的Duck类以及MallardDuck类
public abstract class Duck {
//飞行行为
protected FlyBehavior flyBehavior;
//鸭子叫行为
protected QuackBehavior quackBehavior;
public Duck() {
}
public abstract void display();
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public void swim(){
System.out.println("All ducks float, een decoys");
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
输入并编译FlyBehavior接口与两个行为实现类
public interface FlyBehavior {
//必须实行飞行行为
public void fly();
}
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("i'm flying!");
}
}
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("i can't fly!");
}
}
3.输入并编译QuackBehavior接口及实现类
public interface QuackBehavior {
//必须实现叫的方法
public void quack();
}
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("quack");
}
}
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("squeak");
}
}
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("silence");
}
}
4.输入并编译测试类
public static void main(String[] args) {
//创建一个绿头鸭
Duck mallard = new MallardDuck();
//鸭子飞
mallard.performFly();
//鸭子叫
mallard.performQuack();
}
运行结果
i'm flying!
quack
下一节将会讲动态的设定鸭子行为而不是在鸭子的构造器内实例化。