策略模式

什么是策略模式?

策略模式定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户

设计原则

  1. 找出变化之处,把它们独立出来
  2. 针对接口编程,而不是针对实现编程
  3. 多用组合,少用继承

模拟鸭子游戏

SimUDuck,游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。

使用面向对象的设计模式:设计鸭子的超类BaseDuck,并让各种鸭子继承此超类

public abstract class BaseDuck {
   abstract void display();
}

野鸭子MallardDuck:

public class MallardDuck extends BaseDuck {
    void display() {
        // 我是绿头鸭
    }
    ...
}

红头鸭子RedheadDuck:

public class RedheadDuck extends BaseDuck {
    void display() {
        // 我是红头鸭子
    }
    ...
}

现在我们的让鸭子能飞

  • 方案一:父类增加
public abstract class BaseDuck {
    abstract void display();
    public void fly() {
        // 飞行,可复用
    };
}

问题:并不是所有的鸭子都能飞

  • 方案二:继承
public abstract class BaseDuck {
    abstract void display();
    abstract void fly();
}

问题:每个子类都需要重写, 无法复用

public class RubberDuck extends BaseDuck {
    void display() { 
        // 橡皮鸭 
    }
    void fly() {
        // 覆盖,什么都不做
    }
}
public class DecoyDuck extends BaseDuck {
    void display() { 
        // 诱饵鸭
    }
    void fly() {
        // 覆盖,什么都不做
    }
}
  • 方案三:利用接口,同时增加鸭子叫接口
public interface Flyable {
    fly();
}

public interface Quackable {
    quack();
}
public MallardDuck extends BaseDuck implements Flyable, Quackable {
    void fly() {
        // 翅膀飞行
    }
    
    void quack() {
        // 呱呱叫
    }
}

问题:重复的代码越来越多

解决方案

使用设计原则一:封装变化
使用设计原则二:针对接口编程

  • 抽取变化部分为接口
public interface FlyBehavior {
    void fly();
}

public interface QuackBehavior {
    void quack();
}
  • 把每个行为实现单独作为一个类
public class FlyWithWings implments FlyBehavior {
    void fly() {
        // 使用翅膀飞行
    }
}

public class FlyNoWay implments FlyBehavior {
    void fly() {
        // 什么都不做,不会飞!
    }
}

public class Quack implments QuackBehavior {
    void quack() {
        // 鸭子呱呱叫
    }
}

public class Squeak implments QuackBehavior {
    void quack() {
        // 橡皮鸭子吱吱叫
    }
}

public class MuteQuack implments QuackBehavior {
    void quack() {
        // 什么都不做,不会叫
    }
}
  • 从新定义鸭子超类
public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    void display();
    public void performFly(){
        if (flyBehavior != null) {
            flyBehavior.fly();
        }
    }
    
    public void performQuack(){
        if (quackBehavior != null) {
            quackBehavior.quack();
        }
    }
}
  • 定义鸭子的实体类
public class MallardDuck extends BaseQuack {
    public MallardDuck() {
        // 将鸭子的飞的行为和叫的行为,委托给行为类
        flyBehavior = new FlyBehavior();
        quackBehavior = new QuackBehavior();
    }

    void display() {
        // 野鸭子
    }
}
public class Test {
    public static void main(String[] args){
        Duck duck = new MallardDuck();
        duck.performFly();
        duck.performQuack();
    }
}

问题:MallardDuck内部还是使用了针对实现编程

解决方案

  • 在超类鸭子中增加两个方法
public abstract class Duck {
    ...
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}

  • 动态设置行为
public class Test {
    public static void main(String[] args){
        Duck duck = new MallardDuck();
        duck.setFlyBehavior(new FlyWithWings());
        duck.setQuackBehavior(new Quack());
        duck.performFly();
        duck.performQuack();
    }
}

你可能感兴趣的:(策略模式)