作者:Grey
原文地址:http://www.cnblogs.com/greyzeng/p/5915202.html
模式名称
策略模式(Strategy Pattern)
需求
模拟鸭子游戏,游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。我们应该如何设计这个鸭子类呢?
解决方案
首先,我们可以考虑设计一个鸭子的超类Duck
,抽象出鸭子的公共方法,然后其他鸭子类型继承这个超类,对公共方法有自己独有的实现。
public abstract class Duck {
public abstract void display();
public abstract void quack();
public void swim() {
System.out.println("all ducks can swim");
}
}
public class RedHeadDuck extends Duck {
@Override
public void display() {
System.out.println("This is RedHeadDuck");
}
@Override
public void quack() {
System.out.println("RedHeadDuck Quack");
}
}
public class ModelDuck extends Duck {
@Override
public void display() {
System.out.println("This is ModelDuck");
}
@Override
public void quack() {
System.out.println("ModelDuck Can not Quack");
}
}
但是,这种设计,会出现一个问题:
如果要增加一个可以飞的鸭子,我们在超类中增加一个fly()
方法,所有继承这个超类的子类都会有这个方法,导致代码在多个子类中重复。
public abstract class Duck {
public abstract void display();
public abstract void quack();
public abstract void fly();
public void swim() {
System.out.println("all ducks can swim");
}
}
public class RedHeadDuck extends Duck{
@Override
public void display() {
System.out.println("This is RedHeadDuck");
}
@Override
public void quack() {
System.out.println("Gua Gua Gua~~");
}
@Override
public void fly() {
System.out.println("fly fly fly~~");
}
}
public class ModelDuck extends Duck{
@Override
public void display() {
System.out.println("This is ModelDuck");
}
@Override
public void quack() {
System.out.println("Silence");
}
@Override
public void fly() {
// do nothing
}
}
更好的一种方法:
分开变化与不变化的部分,因为Duck
类里面fly()
和quack()
会随着鸭子的不同而改变,所以我们需要把这两个行为从Duck
里面分离出来,建立一组新类来代表每个行为
QuackBehavior
接口:
interface QuackBehavior {
void quack();
}
QuackBehavior
具体行为:
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("Silence");
}
}
public class Gua implements QuackBehavior {
public void quack() {
System.out.println("Gua Gua Gua~~");
}
}
FlyBehavior
接口:
interface FlyBehavior {
void fly();
}
FlyBehavior
具体行为:
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("fly fly fly~~~");
}
}
public class FlyNoWay implements FlyBehavior {
public void fly() {
// do nothing
}
}
现在鸭子会将飞行和呱呱叫的动作“委托”给FlyBehavior
和QuackBehavior
处理,我们在Duck
中增加两个方performFly()
,performQuack()
public abstract class Duck {
Duck() {}
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public abstract void display();
public void swim() {
System.out.println("all ducks can swim");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
在每种鸭子继承超类Duck
的时候,只需要在构造函数中设置对应的FlyBehavior
和QuackBehavior
实例变量即可。
public class RedHeadDuck extends Duck {
RedHeadDuck() {
this.quackBehavior = new Gua();
this.flyBehavior = new FlyWithWings();
}
@Override
public void display() {
System.out.println("This is RedHeadDuck");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
public class ModelDuck extends Duck {
ModelDuck() {
this.flyBehavior = new FlyNoWay();
this.quackBehavior = new MuteQuack();
}
@Override
public void display() {
System.out.println("This is ModelDuck");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
同时,我们可以在Duck
类中增加对FlyBehavior
和QuackBehavior
的setter/getter
方法,这样我们就可以动态改变鸭子的行为了
public abstract class Duck {
Duck() {}
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public abstract void display();
public void swim() {
System.out.println("all ducks can swim");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
测试代码:
public class DuckTest {
public static void main(String[] args) {
Duck redHeadDuck = new RedHeadDuck();
redHeadDuck.display();
redHeadDuck.performFly();
redHeadDuck.performQuack();
System.out.println();
Duck modelDuck = new ModelDuck();
modelDuck.display();
modelDuck.performFly();
modelDuck.performQuack();
System.out.println();
System.out.println("I want that modelduck can fly");
modelDuck.setFlyBehavior(new FlyWithWings());
modelDuck.performFly();
}
}
输出结果:
This is RedHeadDuck
fly fly fly~~~
Gua Gua Gua~~
This is ModelDuck
can not fly
Silence
I want that modelduck can fly
fly fly fly~~~
完整代码: Strategy Pattern Source