本文已参与「新人创作礼」活动,一起开启掘金创作之路
首先来看看策略模式的概念
策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
(例子参考自《HeadFirst设计模式》)
现在假设有一类鸭子,每类鸭子都有不同的行为,有的可以呱呱叫,有的不能叫,还有的甚至可以飞……
一般的做法就是定义一个Duck的抽象类,把他可能拥有的各类行为都放进去,有多种变化行为的动作定义成抽象类:
public abstrack class Duck {
public void swim(){
System.out.println("每个鸭子都会游泳");
}
public abstract void quack(); //鸭子叫
public abstract void fly(); //鸭子飞
}
但是这样会导致很多问题,比如:如果有五种鸭子的quack行为都是呱呱叫,那么在这五种鸭子的类中会存在相同的代码,在运行的时候也不能动态的改变他们的行为(万一有一种鸭子叫着叫着叫不出来了怎么办),而且这样我们很难得知鸭子的全部行为。
于是我们可以这样做,把鸭子的各种行为分离开来:
//飞行行为的接口
public interface FlyBehavior {
public void fly();
}
//不能飞的实现
public class FlyWithNoWay implements FlyBehavior{
@Override
public void fly() {
System.out.println("当前鸭子不能飞");
}
}
//能飞的实现
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("当前鸭子正在飞");
}
}
//叫声行为的接口
public interface QuackBehavior {
public void quack();
}
//呱呱叫行为的实现
public class Quack implements QuackBehavior{
@Override
public void quack() {
System.out.println("当前鸭子呱呱叫");
}
}
//无法发声行为的实现
public class MuteQuack implements QuackBehavior{
@Override
public void quack() {
System.out.println("当前鸭子不能叫");
}
}
然后我们再修改一下Duck类:
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {}
public void swim() {
System.out.println("鸭子在游泳"); //假设所有的鸭子都会游泳,所以这里直接写出方法体
}
public abstract void display();
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 NormalDuck extends Duck{
public NormalDuck() {
quackBehavior = new Quack(); //定义叫声的行为
flyBehavior = new FlyWithNoWay(); //定义飞行的行为
}
@Override
public void display() {
System.out.println("这是一只正常的鸭子");
}
}
public class NomalDuckTest {
public static void main(String[] args) {
Duck normalDuck = new NormalDuck();
normalDuck.display();
normalDuck.performFly();
normalDuck.performQuack();
}
}
运行结果:
我们也可以在运行过程中动态的改变鸭子的行为:
public class ModelDuck extends Duck{
public ModelDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("这是一只玩具鸭");
}
}
public class ModelDuckTest {
public static void main(String[] args) {
Duck modelDuck = new ModelDuck();
modelDuck.display();
modelDuck.performFly();
modelDuck.performQuack();
System.out.println("玩具鸭摔了一下");
modelDuck.setQuackBehavior(new MuteQuack());
modelDuck.performQuack();
}
}
我们可以看到我们手动把玩具鸭摔一下,然后他就叫不出来了