策略模式也叫政策模式,是一种比较简单的设计模式。它的目的是定义一组算法,将每个算法都封装起来。并且使他们之间可以互换。针对一组算法,将每一个算法封装到具有接口的独立的类中,从而使他们可以相互替换,使得算法可以在不影响到客户端的情况下发生变化。

引入

我们先来看一个示例

  1. // 定义一个抽象类
  2. public abstract class Duck {
  3. public Duck(){}
  4. /**
  5. * 显示鸭子信息
  6. */
  7. public abstract void display();
  8. public void quack() {
  9. System.out.println("鸭字嘎嘎叫~");
  10. }
  11. public void swim(){
  12. System.out.println("dack can swim");
  13. }
  14. public void fly(){
  15. System.out.println("dack can fly");
  16. }
  17. }
  18. // 定义北京鸦
  19. public class PekingDuck extends Duck{
  20. @Override
  21. public void display() {
  22. System.out.println("Pecking Duck");
  23. }
  24. /**
  25. * 因为北京鸦不能飞翔,所以重写fly方法
  26. */
  27. @Override
  28. public void fly() {
  29. System.out.println("Peking Duck can not fly");
  30. }
  31. }
  32. //定义玩具鸦
  33. public class ToyDock extends Duck{
  34. @Override
  35. public void display() {
  36. System.out.println("Tony Duck");
  37. }
  38. // 玩具鸦不会叫,不会飞,不会游泳。
  39. // 所以要重写父类所有方法
  40. @Override
  41. public void quack() {
  42. System.out.println("Tony DUck can not quack");
  43. }
  44. @Override
  45. public void swim() {
  46. System.out.println("Tony Duck can not swim");
  47. }
  48. @Override
  49. public void fly() {
  50. System.out.println("Tony Duck can not fly");
  51. }
  52. }

可以看到,北京鸭和玩具鸦都继承了Duck类,所以fly让所有子类都会飞了,这是不正确的。当然,我么可以通过重写方法来解决,但是一个玩具鸦,我们需要重写父类所有的方法的实现,为了解决这种问题,我们使用策略模式。

image.png
我们就只写fly这一个功能吧。

  1. /**
  2. * 定义一个行为接口
  3. */
  4. public interface FlyBehavior {
  5. void fly();
  6. }
  7. // 实现这个接口
  8. public class GoodFlyBehavior implements FlyBehavior{
  9. @Override
  10. public void fly() {
  11. System.out.println("飞翔技术高超");
  12. }
  13. }
  14. public class BadFlyBehavior implements FlyBehavior{
  15. @Override
  16. public void fly() {
  17. System.out.println("飞翔技术一般");
  18. }
  19. }
  20. public class NoFlyBehavior implements FlyBehavior{
  21. @Override
  22. public void fly() {
  23. System.out.println("不会飞翔");
  24. }
  25. }
  26. // 定义一个抽象类
  27. public abstract class Duck {
  28. /**
  29. * 属性,策略接口
  30. */
  31. FlyBehavior flyBehavior;
  32. public Duck(){}
  33. /**
  34. * 显示鸭子信息
  35. */
  36. public abstract void display();
  37. public void setFlyBehavior(FlyBehavior flyBehavior){
  38. this.flyBehavior = flyBehavior;
  39. }
  40. public void quack() {
  41. System.out.println("鸭字嘎嘎叫~");
  42. }
  43. public void swim(){
  44. System.out.println("dack can swim");
  45. }
  46. public void fly(){
  47. // 对fly进行改进
  48. if (flyBehavior != null){
  49. flyBehavior.fly();
  50. }
  51. }
  52. }
  53. // 不需要自己实现,只需要传入这个行为属性就行了
  54. public class PekingDuck extends Duck{
  55. @Override
  56. public void display() {
  57. System.out.println("Pecking Duck");
  58. }
  59. /**
  60. * 假如北京鸭可以飞翔,但是飞翔技术一般
  61. */
  62. public PekingDuck(){
  63. flyBehavior = new BadFlyBehavior();
  64. }
  65. }

经过上面的改造,我们甚至可以动态的改变某个对象的行为。

public class Client {
    public static void main(String[] args) {
        PekingDuck pekingDuck = new PekingDuck();
        pekingDuck.fly();
        // 动态改变
        pekingDuck.setFlyBehavior(new NoFlyBehavior());
        pekingDuck.fly();
    }
}