CodeEase

策略模式

2015-09-20  本文已影响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 的子类在各自的构造方法中指定自己的行为类。这样策略模式就实现了。

上一篇下一篇

猜你喜欢

热点阅读