设计模式 (一)——策略模式(Strategy,行为型)
2017-02-16 23:21
302 查看
1.概述
使用设计模式可以提高代码的可复用性、可扩充性和可维护性。策略模式(Strategy Pattern)属于行为型模式,其做法是将类所需的行为或者算法一个个封装成单独的类,并将其作为类的数据成员,使得类的行为可以在不改变类设计的情况下灵活变化。2.实例
上面对策略模式的概述难免显得抽象,难于理解,下面给出实例,让我们在实际应用中感受策略模式的做法和作用。2.1丑陋的设计
比如现在我们要设计一款模拟鸭子的游戏:游戏中会出现各种鸭子,一遍游泳戏水,一边呱呱叫。我们采用面向对象技术,先设计一个基类Duck,然后让各种鸭子继承该基类。代码如下://基类Duck class Duck{ public: //呱呱叫 virtual void quack(){ cout<<"呱呱叫"<<endl; } //游泳 virtual void swim(){ cout<<"开始游泳"<<endl; } //飞行 virtual void fly(){ cout<<"开始飞行"<<endl; } //外观展示(纯虚函数,由子类实现) virtual void display()=0; }; //绿头野鸭 class MallardDuck{ public: virtual void display(){ //外观是绿头 } }; //红头鸭 class RedheadDuck{ public: virtual void display(){ //外观是红头 } };
上面的设计使用类继承的方式,复用了不同种类鸭子的公共行为,如游泳、呱呱叫和飞行,也就实现了代码复用。一切看似完美,但是现在我们需要在游戏中增加一个橡皮鸭。按照前面的思维,我们顺其自然的让新的类RubberDuck继承基类Duck,但是橡皮鸭不能飞,叫的声音也和绿头野鸭和红头鸭不一样,于是我们需要在RubberDuck重写基类的fly和quack方法。
class RubberDuck:public Duck{ public: virtual void fly(){ cout<<"我不能飞行"<<endl; } virtual void quack(){ cout<<"吱吱叫"<<endl; } };
现在我们是否能暗自庆幸通过虚函数重写的方法解决了上面的问题,觉得上面的设计令人满意。但是问题来了,如果游戏每六个月更新一次,每次需要加入新的鸭子子类,我们就要被迫检查可能需要重写的fly()和quack()…甚至需要更改基类Duck的设计,加入新的行为方法,这简直是无穷无尽的噩梦。
因为,并非所有的子类都具有飞行和呱呱叫的行为,所以继承并不是合适的解决方式。所以,我们需要让“某些”(而不是全部)鸭子类型可飞或可叫。
2.2合适的设计
现在,我们需要坚持一个面向对象的设计原则:封装变化。找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。该原则把应用中会变化的部分抽取出来封装起来,以便以后可以轻易地改动或扩充,而不影响不需要变化的其他部分。如何设计那组实现飞行和呱呱叫的行为的类呢?我们希望一切能有弹性,能够在游戏运行的过程中动态的改变鸭子的行为。也就是说,我们应该在鸭子类中包含设定行为的方法。有了这个设计目标,我们需要坚持第二个设计原则:针对接口编程,而不是针对实现编程。这里要说明一下,C++的接口指的是抽象类,含有纯虚函数的类[1]。
在此,我们设计两个接口,FlyBehavior和QuackBehavior,还有他们对应的子类,负责实现具体的行为:
//飞行接口,所有飞行类都实现它,所有新的飞行类都必须实现fly()方法 class FlyBehavior{ public: virtual void fly()=0; }; //翅膀飞行类 class FlyWithWings:public FlyBehavior{ public: virtual void fly(){ //实现鸭子飞行 } }; //不飞行类 class FlyNoWay:public FlyBehavior{ public: virtual void fly(){ //什么都不做,鸭子不飞行 } }; //呱呱叫行为接口,一个接口只包含一个需要实现的quack()方法 class QuackBehavior{ public: virtual void quack()=0; }; //真的呱呱叫 class Quack:public QuackBehavior{ public: virtual void quack(){//实现鸭子呱呱叫} }; //吱吱叫 class Squeak:public QuackBehavior{ public: virtual void quack(){//实现鸭子吱吱叫} }; //不叫 class MuteQuack:public QuackBehavior{ public: virtual void quack(){//什么都不做,不会叫} };
这样的设计,可以让飞行和呱呱叫的动作被其他的对象复用,因为这些行为已经与鸭子类无关了。此外,我们也可以新增一些行为,不会影响到既有的行为类,也不会影响“使用”到飞行行为的鸭子类。
下面整合鸭子的行为。将行为类对象作为鸭子类的数据成员,并提供动态改变行为的方法,具体实现如下:
//橡胶鸭类 class RubberDuck { private: FlyBehavior* flyBehavior; QuackBehavior* quackBehavior; public: RubberDuck() { flyBehavior = new FlyNoWay(); quackBehavior = new Squeak(); } //飞行行为 void performFly() { flyBehavior->fly(); } //改变飞行行为 void setFlyBehavior(FlyBehavior* flyB) { flyBehavior = flyB; } //呱呱叫行为 void performQuack() { quackBehavior->quack(); } //改变叫声 void setPerformQuack(QuackBehavior* quackB) { quackBehavior = quackB; } //其他行为方法及析构函数 ... };
上面就可以动态地改变了鸭子对象的飞行方式和呱呱叫行为,因为每一个鸭子都有一个FlyBehavior和一个QuackBehavior,将飞行和呱呱叫委托给它们代为处理。
当你将两个类结合起来使用,如同上面的例子,这就是组合(composition)。这种做法和“继承”不同的地方在于,鸭子的行为不是继承来的,而是和适当的行为对象“组合”而来。这是一个很重要的技巧,其实是使用了我们的第三个设计原则:多用组合,少用继承。
如你所见,使用组合建立系统具有很大的弹性,不仅可将算法族封装成类,更可以“在运行时动态地改变行为“。组合可以用在许多设计模式中,有优点,但也有缺点。
3.小结
(1)使用设计模式可以提高代码的可复用性、可扩充性和可维护性;(2)OO(Object Oriented,面向对象)的基础是:抽象、封装、继承与多态;
(3)本文提到的OO原则有:
(3.1)封装变化。找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起;
(3.2)针对接口编程,不针对实现编程;
(3.3)多用组合,少用继承。
(4)策略模式:定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
(5)在面向对象设计时,没有找到适当的模式解决问题时,要想建立可维护的OO系统,要诀在于随时想到系统以后可能需要的变化以及应对变化的原则。
参考文献
[1]标准C++中有没有接口和纯抽象类的概念?[2]Freeman E.,Freeman E.,Sierra K.,et al.设计模式[M].第一版O’Reilly Taiwan公司译.北京:中国电力出版社,2015:1-32
相关文章推荐
- 设计模式之七:Strategy(策略)—对象行为型模式
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式(十三)策略模式(Strategy)-行为型
- [导入]C#面向对象设计模式纵横谈(23):(行为型模式) Strategy 策略模式.zip(8.00 MB)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- [设计模式-行为型]策略模式(Strategy)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式(21)-行为型-策略模式(Strategy)
- 设计模式--策略模式Strategy(行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式22:Strategy 策略模式(行为型模式)
- 设计模式18---设计模式之策略模式(Strategy)(行为型)