《Head First 设计模式》之策略模式

作者: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
    }
}

现在鸭子会将飞行和呱呱叫的动作“委托”给FlyBehaviorQuackBehavior处理,我们在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的时候,只需要在构造函数中设置对应的FlyBehaviorQuackBehavior实例变量即可。

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类中增加对FlyBehaviorQuackBehaviorsetter/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

原文地址:https://www.cnblogs.com/greyzeng/p/5915202.html