什么是策略模式

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要是为了解决在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

场景

假设我们现在有一群鸭子,有橡皮鸭和丑小鸭,橡皮鸭不能飞不能叫,丑小鸭能飞能叫,它们都可以游泳。 我们可以先把飞行这两个行为抽象出两个接口,然后再去实现这两个接口。

/**
 * 飞行行为接口
 *
 * @author 李寻欢
 * @date 2020/5/26 2:13 下午
 */
public interface FlyBehavior {
    /**
     * 飞行行为
     */
    void fly();
}

/**
 * 飞行行为实现:不能飞
 *
 * @author 李寻欢
 * @date 2020/5/26 2:30 下午
 */
public class CantFly implements FlyBehavior {

    /**
     * 飞行行为
     */
    @Override
    public void fly() {
        System.out.println("劳资不会飞啊~~");
    }
}
/**
 * 叫声行为接口
 *
 * @author 李寻欢
 * @date 2020/5/26 2:13 下午
 */
public interface QuackBehavior {
    /**
     * 叫声行为
     */
    void quack();
}

/**
 * 叫声行为实现:不会叫
 *
 * @author 李寻欢
 * @date 2020/5/26 2:34 下午
 */
public class CantQuack implements QuackBehavior {
    /**
     * 叫声行为
     */
    @Override
    public void quack() {
        System.out.println("我不会叫!!!");
    }
}

接口抽象出来之后,我们还需要一个叫鸭子的基类,作为不同鸭子种类的父类。

/**
 * 鸭子基类
 *
 * @author 李寻欢
 * @date 2020/5/26 2:14 下午
 */
public abstract class Duck {
    /**
     * 通过继承封装一定存在的必要内容,等待子类重写:比如鸭子的描述
     */
    abstract void display();

    /**
     * 飞行行为是动态的,可能会变,所以抽象出来
     */
    FlyBehavior flyBehavior;

    /**
     * 鸭子的叫声不同,所以也抽象出来
     */
    QuackBehavior quackBehavior;


    /**
     * 处理飞这个行为
     */
    void performFly() {
        flyBehavior.fly();
    }

    /**
     * 处理叫这个行为
     */
    void performQuack() {
        quackBehavior.quack();
    }

    /***
     * 通过继承封装不变的内容:假设所有鸭子都会游泳
     */
    void performSwim() {
        System.out.println("我会游泳!!");
    }
}

这时候我们就可以生成橡皮鸭丑小鸭了。

/**
 * 我是一只橡皮鸭
 *
 * @author 李寻欢
 * @date 2020/5/26 2:39 下午
 */
public class RubberDuck extends Duck {

    /**
     * 给定一个不会飞和不会叫的行为
     */
    RubberDuck() {
        flyBehavior = new CantFly();
        quackBehavior = new CantQuack();
    }

    /**
     * 通过继承封装一定存在的必要内容,等待子类重写:比如鸭子的描述
     */
    @Override
    void display() {
        System.out.println("我是一只橡皮鸭");
    }
}


/**
 * 我是一只丑小鸭
 *
 * @author 李寻欢
 * @date 2020/5/26 2:41 下午
 */
public class WoodDuck extends Duck {

    /**
     * 设定可以通过翅膀飞行和嗷嗷叫的行为
     */
    WoodDuck() {
        flyBehavior = new FlyWithWings();
        quackBehavior = new AoQuack();
    }

    /**
     * 通过继承封装一定存在的必要内容,等待子类重写:比如鸭子的描述
     */
    @Override
    void display() {
        System.out.println("我是一只丑小鸭……");
    }
}

好了,到这儿就基本上差不多了,我们来写个 Demo 试试看效果。

public static void main(String[] args) {
    // 橡皮鸭
    Duck rubber = new RubberDuck();
    rubber.display();
    rubber.performFly();
    rubber.performQuack();
    rubber.performSwim();

    // 丑小鸭
    Duck wood = new WoodDuck();
    wood.display();
    wood.performFly();
    wood.performQuack();
    wood.performSwim();
}

// 输出效果:
// 我是一只橡皮鸭
// 劳资不会飞啊~~
// 我不会叫!!!
// 我会游泳!!
// ================
// 我是一只丑小鸭……
// 我可以用翅膀飞……
// 我会嗷嗷叫~~
// 我会游泳!!

后记

主要是写给自己看的,着实写得乱七八糟的,就这样吧,能看懂就行~~