1. 设计原型 - a Duck
说明:
-
我们假设所有的Duck叫声都一样,quack~~,游泳的姿态也相同~~
-
每种Duck的外型特征彼此不同 ~~
-
图示中斜体文字表示, 函数被virtual xxx = 0 关键字所声明,为抽象接口。对应的代码如下,以后不再追加代码。
#include <iostream> using namespace std; class Duck { public: virtual void quack(void) { cout << "all Ducks quack" << endl; } virtual void swim(void) { cout << "all Ducks swim" << endl; } virtual void display(void) = 0; }; class MallardDuck : public Duck { public: void display (void) { cout << "A MallardDuck display" << endl; } }; class RedheadDuck : public Duck { public: void display (void) { cout << "A RedheadDuck display" << endl; } }; int main() { MallardDuck aMallardDuck; RedheadDuck aRedheadDuck; aRedheadDuck.quack(); aMallardDuck.quack(); aRedheadDuck.display(); aMallardDuck.display(); return 0; } ————————————————————————打印输出——————————————— all Ducks quack all Ducks quack A RedheadDuck display A MallardDuck display
2. 设计原型的改进-飞行能力
**需求:**我们需要为Duck 添加飞行功能的支持
方案: 基类Duck中添加fly接口,这样所有子类都具备了fly的能力
virtual void Ducks::fly(void)
{
cout << "all Ducks fly" << endl;
}
**问题:**考虑橡胶制成的小鸭子,它应该具有飞行能力吗?
橡胶Duck不具备飞行能力,所以这个设计有问题
3. 小节2 提出的问题的修改提案
方案1:
virtual void Ducks::fly(void); 可以在RubberDuck中override 此函数,什么也不做即可
问题:
与方案1类似,RedheadDuck,MallardDuck 叫声和游泳姿态各不相同,因此有必要overrid Duck中的quack 和 swim函数
方案1的改进方案2
void RubberDuck::fly()
{
cout << "RubberDuck does not fly" << endl;
}
...
void RedhatDuck::swim()
{
cout << "swim like a RedhatDuck" << endl;
}
void RedhatDuck::quack()
{
cout << "quack like a RedhatDuck" << endl;
}
...
void MallardDuck::swim()
{
cout << "swim like a MallardDuck" << endl;
}
void MallardDuck::swim()
{
cout << "quack like a MallardDuck" << endl;
}
改进方案2的问题
如果我们有100种Duck呢? 如果以后需要添加类似likefly的功能函数,,但为了避免bug, 在子类中需要重写100次如下的函数。
尽管likefly函数毫无用处。
void RubberDuck::likefly()
{
cout << "RubberDuck does not fly" << endl;
}
不如,考虑重构?
4. 设计原型的重构
说明:
-
Duck 是一个抽象概念,具有飞行行为,游泳行为,叫声行为。 对于Duck来说,行为不再表现为函数,而是对象 FlyBehavior …
优点: -
代码复用性强。RedHeadDuck 和 MallardDuck 可以复用一个FlywithWings 类
代码:
/****************************************************************************** Online C++ Compiler. Code, Compile, Run and Debug C++ program online. Write your code in this editor and press "Run" button to compile and execute it. *******************************************************************************/ #include <iostream> using namespace std; class SwimBehavior { public: virtual void swim(void) = 0; }; class QuackBehavior { public: virtual void quack(void) = 0; }; class FlyBehavior { public: virtual void fly(void) = 0; }; class SwimCircle : public SwimBehavior { public: void swim (void) { cout << "swim in a circle" << endl; } }; class SwimLine : public SwimBehavior { public: void swim(void) { cout << "swim in a line" << endl; } }; class MuteQuack: public QuackBehavior { public: void quack(void) { cout << "quack in mute way" << endl; } }; class Squeak: public QuackBehavior { public: void quack(void) { cout << "quack in Squeak way" << endl; } }; class FlyNoWay : public FlyBehavior { public: void fly(void) { cout << "fly do nothing" << endl; } }; class FlywithWings : public FlyBehavior { public: void fly(void) { cout << "fly with wings" << endl; } }; class Duck { public: void performFly() { m_flaybehavior->fly(); } void performSwim() { m_quackbehavior->quack(); } void performQuack() { m_swimbehavior->swim(); } protected: FlyBehavior *m_flaybehavior; QuackBehavior *m_quackbehavior; SwimBehavior *m_swimbehavior; }; class RedHeadDuck: public Duck { public: RedHeadDuck (void) { m_flaybehavior = new FlywithWings(); m_swimbehavior = new SwimCircle(); m_quackbehavior = new Squeak(); } }; class MallardDuck: public Duck { public: MallardDuck (void) { m_flaybehavior = new FlywithWings(); m_swimbehavior = new SwimCircle(); m_quackbehavior = new MuteQuack(); } }; int main() { MallardDuck mallarDuck; RedHeadDuck redHeadDuck; mallarDuck.performQuack(); mallarDuck.performSwim(); mallarDuck.performFly(); cout << "--------cut line-------" << endl; redHeadDuck.performQuack(); redHeadDuck.performSwim(); redHeadDuck.performFly(); return 0; }
5. 小节4重构的一个应用
需求: 乘火箭而飞的鸭子
设计:
代码:
class FlyOnRocket: public FlyBehavior
{
public:
void fly()
{
cout << "I am flying on Rockets" << endl;
}
};
class SuperDuck: public Duck
{
public:
SuperDuck (void)
{
m_flaybehavior = new FlyOnRocket();
m_swimbehavior = new SwimCircle();
m_quackbehavior = new MuteQuack();
}
};
int main()
{
SuperDuck superduck;
superduck.performFly();
return 0;
}