目录
1.模式的演进
1.1 简单的模拟鸭子应用(例子)
模拟鸭子应用:
鸭子的方法:quack(叫)、swim(游泳)、display(外观)、fly(飞行)
但是并不是所有鸭子都拥有全部方法,并且方法的实现也会有不同
橡皮鸭是吱吱叫、不会飞
诱饵鸭不会叫也不会飞
面对这些问题你将如何设计模式?
1.2 方法一:继承
最先想到的会是继承的方法
思路:对超类Duck进行继承,对具体的鸭子进行方法的覆盖
缺点:每次有加入新的鸭子类就会对所有的方法进行检查(选择是否覆盖)、这样有相同的行为代码就不能复用了。
1.3 方法二:接口
使用接口进行选择方法的实现(主要争对java)
思路:如果你有飞的行为就实现接口就行了,可以减少继承的必须检查(如果没有飞的行为不实现就行了)
缺点:仍然没有解决代码复用问题,并且java接口没有默认方法这样更加加大了代码的书写
1.4 策略模式
我们发现quack和fly两种方法会变化,所以我们将其分离(分别设计两组类
组合:使用组合将鸭子类和它的行为类进行连接
针对接口编程:每种行为都有一个超类,然后下面是一组对应的行为,这样就可以实现对接口编程(使用多态选择不同行为)
只要写一种行为,凡是有这种行为的鸭子都可以使用这一个行为
1.5 动态设定行为
使用策略模式,因为叫和飞行的行为都是组合,并且使用多态进行选择,所以我们可以在运行中也可以动态改变行为
2. 模式实现以及部分源码
2.1总类图
2.2 部分源码
2.2.1 Duck.h
#include "FlyBehavior.h"
#include "QuackBehavior.h"
class Duck{
public:
//组合飞行和叫的行为
FlyBehavior *flyBehavior;
QuackBehavior *quackBehavior;
Duck();
void swim();
virtual void display()=0;//由子类实现
void performQuack();
void performFly();
void setFlyBehavior(FlyBehavior *f);
void setQuackBehavior(QuackBehavior *q);
virtual ~Duck();
};
2.2.2 MallardDuck.h
#include "Duck.h"
class MallardDuck:public Duck{
public:
MallardDuck();
virtual void display()override final;//实现外观
virtual ~MallardDuck();
};
2.2.3 FlyBehavior.h
class FlyBehavior{
public:
virtual void fly()=0;
virtual ~FlyBehavior(){};
};
2.2.4 FlyNoWay.h
#include "FlyBehavior.h"
class FlyNoWay:public FlyBehavior{
public:
virtual void fly()override final;
virtual ~FlyNoWay();
};
3.总结
1.策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
2.设计原则:
(1)找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
(2)针对接口编程,而不是针对实现编程
(3)多用组合,少用继承