假设现在有一个模拟鸭子的戏,此游戏设计了一个鸭子超类(Superclass),在超类中定义鸭子的形为 quack和swim,并让其它的鸭子继承此超类。类图如下:
但假设现在鸭子的形为要扩展,要有一个会飞的行为,这时只需在基类Duck中添加fly()即可,类图如下:
但有一个问题是并非所有的鸭子都会飞,那么在超类中添加一个形为时,所有的子类中都会有这个行为,有一个解决方法是我们在不会飞 的鸭子中覆盖掉fly()行为,但当有更多的行为加进来时,这样的维护量是不可接受的,显然继承不是这里可以解决问题的最好方法。软件开发的一个不变的真理就是软件要一直改变,否则软件就会“死亡”。这就引出了第一个设计原则:找出应用程序中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
我们希望鸭子的行为有弹性,因为没有弹性就会走到上面所述的困境中。有弹性的一个方法就是将鸭子的行为放在分开的类中,此类专门提供某种行为接口的实现。
设计原则二:针对接口编程,而不是针对实现编程
我们设计专门的接口代表每个行为,比方说,FlyBehavir与QuackBehavior而行为的每个实现都将实现其中的一个接口。
行为类的类图如下所示:
这样的设计,可以让飞行和呱呱叫的动作被其他的对象复用,因为这些行为已经与鸭子类无关了。而我们可以新增一些行为,不会影响到既有的行为类,也不会影响“使用”到飞行行为的鸭子类。
修改Duck的设计,在其中添加两个变量分别为flyBehavior和quackBehavior, 这两个变量声明为接口,这样每个鸭子都可以动态的设置这些变量以在运行时引用正确的行为类型。同时删除fly和quack方法,类图如下:
#include <iostream>
using namespace std;
class FlyBehavior
{
public:
FlyBehavior(){}
virtual ~FlyBehavior(){}
virtual void fly();
};
class FlyWithWings : public FlyBehavior
{
public:
FlyWithWings(){}
virtual ~FlyWithWings(){}
virtual void fly();
};
class FlyNoWay : public FlyBehavior
{
public:
FlyNoWay(){}
virtual ~FlyNoWay(){}
virtual void fly();
};
class QuackBehavior
{
public:
QuackBehavior(){}
virtual ~QuackBehavior(){}
virtual void quack();
};
class Quack : public QuackBehavior
{
public:
Quack(){}
virtual ~Quack(){}
virtual void quack();
};
class MuteQuack : public QuackBehavior
{
public:
MuteQuack(){}
virtual ~MuteQuack(){}
virtual void quack();
};
class Squeak : public QuackBehavior
{
public:
Squeak(){}
virtual ~Squeak(){}
virtual void quack();
};
class Duck
{
public:
Duck(){}
~Duck(){}
void performQuack();
void swim();
void display();
void performFly();
protected:
FlyBehavior *flyBehavior;
QuackBehavior *quackBehavior;
};
class MallardDuck : public Duck
{
public:
MallardDuck();
~MallardDuck();
};
#include "strategy.h"
void FlyBehavior::fly()
{
}
void FlyWithWings::fly()
{
cout << " fly with wings" << endl;
}
void FlyNoWay::fly()
{
cout << "I can't fly" << endl;
}
void QuackBehavior::quack()
{
}
void Quack::quack()
{
cout << "Quack" << endl;
}
void MuteQuack::quack()
{
cout << "Silence" << endl;
}
void Squeak::quack()
{
cout << "Squeak" << endl;
}
void Duck::performQuack()
{
quackBehavior -> quack();
}
void Duck::swim()
{
cout << "I'm swiming" << endl;
}
void Duck::display()
{
cout << "display" << endl;
}
void Duck::setQuackBehavior(QuackBehavior qb)
{
quackBehavior = qb;
}
MallardDuck::MallardDuck()
{
flyBehavior = new FlyWithWings;
quackBehavior = new Quack;
}
MallardDuck::~MallardDuck()
{
delete flyBehavior;
delete quackBehavior;
}
int main(int argc, char** argv)
{
MallardDuck *duck = new MallardDuck;
duck -> performFly();
duck -> performQuack();
}
上面的DUCK的子类初始化时就设定好了鸭子的行为,下面是动态的设定鸭子的行为。在 duck类中新增两个方法:类图如下
代码如下:
#include <iostream> using namespace std; class FlyBehavior { public: FlyBehavior(){} virtual ~FlyBehavior(){} virtual void fly(); }; class FlyWithWings : public FlyBehavior { public: FlyWithWings(){} virtual ~FlyWithWings(){} virtual void fly(); }; class FlyNoWay : public FlyBehavior { public: FlyNoWay(){} virtual ~FlyNoWay(){} virtual void fly(); }; class FlyRocketPowered : public FlyBehavior { public: FlyRocketPowered(){} virtual ~FlyRocketPowered(){} virtual void fly(); }; class QuackBehavior { public: QuackBehavior(){} virtual ~QuackBehavior(){} virtual void quack(); }; class Quack : public QuackBehavior { public: Quack(){} virtual ~Quack(){} virtual void quack(); }; class MuteQuack : public QuackBehavior { public: MuteQuack(){} virtual ~MuteQuack(){} virtual void quack(); }; class Squeak : public QuackBehavior { public: Squeak(){} virtual ~Squeak(){} virtual void quack(); }; class Duck { public: Duck(){} virtual ~Duck(){} void performQuack(); void swim(); virtual void display(); void performFly(); void setFlyBehavior(FlyBehavior *fb); void setQuackBehavior(QuackBehavior *qb); protected: FlyBehavior *flyBehavior; QuackBehavior *quackBehavior; }; class MallardDuck : public Duck { public: MallardDuck(); virtual ~MallardDuck();
#include "strategy.h" void FlyBehavior::fly() { } void FlyWithWings::fly() { cout << " fly with wings" << endl; } void FlyNoWay::fly() { cout << "I can't fly" << endl; } void FlyRocketPowered::fly() { cout << "I'm flying with a rocket!"; } void QuackBehavior::quack() { } void Quack::quack() { cout << "Quack" << endl; } void MuteQuack::quack() { cout << "Silence" << endl; } void Squeak::quack() { cout << "Squeak" << endl; } void Duck::performQuack() { quackBehavior -> quack(); } void Duck::swim() { cout << "I'm swiming" << endl; } void Duck::display() { cout << "display" << endl; } void Duck::performFly() { flyBehavior -> fly(); } void Duck::setFlyBehavior(FlyBehavior *fb) { flyBehavior = fb; } void Duck::setQuackBehavior(QuackBehavior *qb) { quackBehavior = qb; } MallardDuck::MallardDuck() { flyBehavior = new FlyWithWings; quackBehavior = new Quack; } MallardDuck::~MallardDuck() { delete flyBehavior; delete quackBehavior; } void MallardDuck::display() { cout << "I'm a mallarDuck"; } ModelDuck::ModelDuck() { flyBehavior = new FlyNoWay; quackBehavior = new Quack; } ModelDuck::~ModelDuck() { delete flyBehavior; delete quackBehavior; } int main(int argc, char** argv) { MallardDuck *duck = new MallardDuck; duck -> performFly(); duck -> performQuack(); Duck *model = new ModelDuck; model -> performFly(); model -> setFlyBehavior(new FlyRocketPowered); model -> performFly(); }
virtual void display();};class ModelDuck : public Duck{public:ModelDuck();virtual ~ModelDuck();};