1. 策略模式

设计原则

  • 找出应用中可能需要变化之处,把它们独立出来。不要和那些不需要变化的代码混在一起
  • 针对接口编程,而不是针对实现编程
  • 多用组合,少用继承

定义和实现思路

定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
  • 把算法动机使用接口抽象
  • 实现算法动机的接口,实现具体算法行为
  • 在使用此类算法的客户中,使用算法接口持有实例变量
  • 在客户中,把算法行为委托给实例变量
  • 并且可以提供setter方法,在运行时动态更改具体的算法行为

UML模型

策略模式.jpg

具体代码

/**
 * 接口封装行为
 *
 * @author luhuancheng
 * @since 2018/3/25 21:56
 */
public interface FlyBehavior {

    void fly();

}
/**
 * 实现行为接口,封装具体行为
 *
 * @author luhuancheng
 * @since 2018/3/25 21:57
 */
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I'm flying!");
    }
}


/**
 * 接口封装行为
 *
 * @author luhuancheng
 * @since 2018/3/25 21:55
 */
public interface QuackBehavior {

    void quack();

}
/**
 * 实现行为接口,封装具体行为
 *
 * @author luhuancheng
 * @since 2018/3/25 21:58
 */
public class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Quack!");
    }
}

/**
*
*抽象超类,用实例变量组合两个接口的实现类实例
*/
public abstract class Duck {

    QuackBehavior quackBehavior;

    FlyBehavior flyBehavior;

    /**
     * 委托给具体的行为类
     */
    public void performQuack() {
        quackBehavior.quack();
    }

    /**
     * 委托给具体的行为类
     */
    public void performFly() {
        flyBehavior.fly();
    }

    public abstract void display();

    public void swim() {
        System.out.println("Duck swim");
    }

    /**
     * 运行时动态改变具体行为
     * @param quackBehavior
     */
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }

    /**
     * 运行时动态改变具体行为
     * @param flyBehavior
     */
        public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
}
/**
 * 将不变的代码封装在超类(Duck)中,把变化的代码用接口抽象,并且使用组合的方式把接口的具体方式引入。
 * 通过委托的方式执行具体的行为
 *
 * @author luhuancheng
 * @since 2018/3/25 22:11
 */
public class MallardDuck extends Duck {

    public MallardDuck() {
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    @Override
    public void display() {
        System.out.println("I'm a real Mallard duck");
    }
}

/**
 * 客户端类
 *
 * @author luhuancheng
 * @since 2018/3/25 22:16
 */
public class Client {

    public static void main(String[] args) {
        Duck mallard = new MallardDuck();
        mallard.performFly();
        mallard.performQuack();
    }

}

调用时序图

策略模式时序图.png

总结

  • 我们把两类算法(即QuackBehavior、FlyBehavior)抽象为接口
  • 每一类算法都可以提供形态、方式各异的具体逻辑(此例的实现为QuackBehavior -> Quack;FlyBehavior -> FlyWithWings)
  • 在抽象超类中(Duck)使用实例变量持有以上两类算法(即QuackBehavior、FlyBehavior),并且提供了运行时动态改变算法行为的setter方法(setQuackBehavior、setFlyBehavior)。这就实现了在客户端类中,可以调用这两个方法,按需设置实现了接口(QuackBehavior、FlyBehavior)的各种算法实现。剥离了代码中经常变化的部分
  • 提供代理方法,执行算法操作(performQuack、performFly)

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