0%

从0开始学java 02 :委托与策略模式

生活所迫呀。

上一期中,我们通过接口(interface)和抽象类(abstract class)理解了如何定义行为规范、如何实现多态等等。然而,在传统的继承方式中,子类通过覆盖方法来改变行为,但这种方式在面对行为切换、行为复用时显得僵硬。因此,我们希望有一种方式,不用继承,也能改变对象的行为,更适合“插件式”的行为结构。

这个时候,就需要一种新的模式委托,把行为交给另一个对象来完成。

首先,我们需要先定义一个接口,来规范要干的事情

1
2
3
public interface FlyBehavior{
void fly();
}

实现接口的类必须要实现fly这一个动作,我们定义一个实现FlyBehavior接口的类FlyWithWings,来实现有翅膀可以飞的动作:

1
2
3
4
5
public class FlyWithWings implements FlyBehavior{
public void fly(){
System.out.println("fly!!!!")
}
}

我们再定义一个实现FlyBehavior接口的类FlyNoWings,来实现没翅膀不能飞的动作:

1
2
3
4
5
public class FlyNoWings implements FlyBehavior{
public void fly(){
System.out.println("cannot fly!!!!")
}
}

定义玩接口和接口的实现之后,我们定义了两个飞行动作,现在,我们来定义实现飞行动作的对象。
我们定义一个鸭子抽象类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public abstract class Duck{
// 声明引用变量
FlyBehavior flyBehavior;

// 构造函数
public Duck(){

}

// 抽象类的函数,子类必须实现
public abstract void display();

// 委托给行为类
public void performFly() {
flyBehavior.fly();
}
}

这里首先声明了一个FlyBehavior类型的引用变量,表示鸭子的飞行行为,当调用performFly()时,实际上调用的是flyBehavior对象的fly()方法。

好的,那么我们可以新建一个子类了:

1
2
3
4
5
6
7
8
9
public class MallardDuck extends Duck{
public MallardDuck(){
flyBehavior = new FlyNoWings();
}

public void display() {
System.out.println("im MallardDuck")
}
}

在 MallardDuck 构造函数里,给继承自父类的 flyBehavior 变量赋值为 new FlyWithWings() 实例。这样调用 performFly() 就会调用 FlyWithWings 类的 fly() 方法,实现“飞”的动作。
入口:

1
2
3
4
5
6
public class RunDuck {
public static void main(String[] args){
Duck mallard = new MallardDuck();
mallard.performFly();
}
}

输出: cannot fly!!!

但是,这样还是不够灵活,我们还想要让鸭子具有动态行为。为了实现这个目的,我们只需要在抽象类中加入一个设定方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class Duck{
FlyBehavior flyBehavior;

public Duck(){

}

public abstract void display();

public void performFly() {
flyBehavior.fly();
}

// 新加入的方法
public void setFlyBehavior(FlyBehavior fb){
flyBehavior = fb;
}
}

随后,在实现时:

1
2
3
4
5
6
7
8
public class RunDuck {
public static void main(String[] args){
Duck mallard = new MallardDuck();
mallard.performFly();
mallard.setFlyBehavior(new FlyWithWings());
mallard.performFly();
}
}

即可动态设定其行为,输出为:
cannot fly!!!
fly!!!

这种通过组合行为接口的方式实现动态切换行为的设计模式,称为策略模式(Strategy Pattern),是面向对象设计中的重要思想