策略模式

作者: 贾佳菊 | 来源:发表于2015-09-20 22:31 被阅读116次

    策略模式:定义算法族,封装起来,让算法独立于使用算法的类。

    原则:

    1. 封装变化;
    2. 多用组合,少用继承;
    3. 针对接口编程,不针对实现编程。

    设计一个模拟鸭子应用,如果不使用策略模式,大致结构是这样的:

    只考虑继承的模拟鸭子类图.png

    红头鸭、绿头鸭、橡皮鸭、诱饵鸭有共同的父类,它们分别实现自己的 fly() 和 quack() 方法,比如红头呀能叫能飞,橡皮鸭能叫不能飞,诱饵鸭不能飞不能叫……
    在这个设计下,每定义一个新的鸭子都要重写这个类下的 fly() 和 quack() 方法,这会导致大量实现 fly() 和 quack() 方法的重复代码,也就是说 fly() 和 quack() 这两个行为和“鸭子类”耦合在了一起。这些代码是容易变化的,要把它们从原来的类中分离出来重新封装(即 1. 封装变化),通过组合而不是继承来与“鸭子类”配合(即 2. 多用组合,少用继承。大多数情况下继承意味着耦合)。然后再根据具体的行为来实现代码(即 3. 针对接口编程)。

    使用策略模式后的类图:

    策略模式模拟鸭子类图.png

    使用策略模式,将 Fly 和 Quack 行为分离出来,封装成一个接口,使用行为类实现分别实现不同的行为。在 Duck 中设置两个实例变量分别引用它们。这样,之后可以更好的应对这部分的变化。在子类化 Duck 时,也可以动态的指定子类的行为。并通过调用 perfrom 方法委托行为类来实现行为。

    CPP 的实现:

    Duck 类:

    class Duck {
    public:
      Duck() = default;
      ~Duck();
    
      FlyBehavior *flyBehavior;
      QuackBehavior *quackBehavior;
    
      void swim();
      void display();
      void perfromQuack();
      void perfromFly();
      void setFlyBehavior(FlyBehavior *flyBehavior);
      void setQuackBehavior(QuackBehavior *quackBehavior);
    };
    

    两个行为接口,CPP 中没有 Java 中的 interface 的概念。使用抽象基类实现:

    class FlyBehavior {
    public:
      virtual void fly() const = 0;
    };
    
    class QuackBehavior {
    public:
      virtual void quack() const = 0;
    };
    

    定义具体的行为类实现抽象行为基类的接口,Duck 的子类在各自的构造方法中指定自己的行为类。这样策略模式就实现了。

    相关文章

      网友评论

        本文标题:策略模式

        本文链接:https://www.haomeiwen.com/subject/uoficttx.html