文章目录
一、预热
什么是设计模式:设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。
设计模式目标:可复用
思维模式比代码技巧更重要,设计原则比模式更重要!
二、设计原则
- 依赖倒置原则(DIP)
稳定应该依赖于稳定,不能有对变化的依赖。对变化应该隔离开。 - 开放封闭原则(OCP)
对扩展开放,对更改封闭。类模块应该是可扩展的,但是不可修改。 - 单一职责原则(SRP)
一个类应该仅有一个引起它变化的原因,变化的方向隐含着类的责任。 - 里氏代换原则 Liskov(LSP)
子类必须能替换它们的基类(IS-A),继承表达类型抽象。 - 接口隔离原则(ISP)
接口应该小而完备。 - 优先使用对象组合,而不是类继承
继承在某种程度上破坏了封装性,子类父类耦合度高。但也不是说不能用继承,某些情况下可能继承更适合。 - 封装变化点
将稳定和变化的部分隔离开,出现变化时,稳定部分不需要改动。 - 针对接口编程,而不是针对实现编程
不将变量类型声明为某个特定的具体类,而是声明为某个接口。
客户程序无需知道对象的具体类型,只需要知道对象所具有的接口。
减少系统中各部分的依赖关系,从而实现“高内聚、松耦合”的类型设计方案。
三、GOF-23模式分类、重构
3.1 模式分类
- 从目的来看:
- 创建型( Creational)模式: 将对象的部分创建工作延迟到类或者其他对象,从而应对需求变化为对象创建时具体类型现引来的冲击。
包括:单例模式,简单工厂模式,抽象工厂模式,工厂方法模式,原型模式,建造者模式 - 结构型( Structural)模式: 通过类继承或者对象组合获得更活的结构,从而应对需求变化为对象的结构带来的冲击。
包括:适配器模式,桥接模式,组合模式,装饰模式,外观模式,享元模式,代理模式 - 行为型( Behavioral)模式: 通过类继承或者对象组合来划类与对象间的职责,从而应对需求变化为多个交互的对象带的冲击。
包括:职责链模式,命令模式,解释器模式,迭代器模式,中介者模式,备忘录模式,观察者模式,状态模式,策略模式,模板方法模式,访问者模式
- 从范围来看:
- 类模式处理类与子类的静态关系。
- 对象模式处理对象间的动态关系。
3.2 重构关键技法
- 静态 —> 动态
- 早绑定 —> 晚绑定
- 继承 —> 组合
- 编译时依赖 —> 运行时依赖
- 紧耦合 —> 松耦合
四、TemplateMethod Mode 模板方法模式
定义一个操作中的算法的骨架 (稳定),而将一些步骤延迟(晚绑定)到子类中。 Template ethod使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的某些特定步骤。
模板方法实现了一个算法的框架,有些步骤可能是固定不变的,不需要暴露给用户,而有些步骤是允许用户重写的,这些步骤会被封装成一个或多个方法,以虚函数的形式提供给用户,允许用户自己实现。
在下面的代码中,抽象基类的TemplateMethod方法中可能还有其它的步骤,不止这两个。用户只需要根据实际情况重写这些接口即可,不用关心整体的工作流程。(稳定的框架为非虚方法,可变化的步骤为虚方法)
#include <iostream>
using namespace::std;
class AbstractClass
{
public:
void TemplateMethod() {
CustomOperation1();
CustomOperation2();
}
protected:
//抽象基类定义的默认Operation
virtual void CustomOperation1() {
cout << "Default Operation1." << endl;
}
virtual void CustomOperation2() {
cout << "Default Operation2." << endl;
}
};
class ConcreteClassA : public AbstractClass
{
public:
//具体类重写的Operation
virtual void CustomOperation1() {
cout << "ConcreteA Operation1." << endl;
}
virtual void CustomOperation2() {
cout << "ConcreteA Operation2." << endl;
}
};
class ConcreteClassB : public AbstractClass
{
public:
//具体类重写的Operation
virtual void CustomOperation1() {
cout << "ConcreteB Operation1." << endl;
}
virtual void CustomOperation2() {
cout << "ConcreteB Operation2." << endl;
}
};
int main(void)
{
AbstractClass * pAbstract = new AbstractClass();
pAbstract->TemplateMethod();
AbstractClass * pConcreteA = new ConcreteClassA();
pConcreteA->TemplateMethod();
AbstractClass * pConcreteB = new ConcreteClassB();
pConcreteB->TemplateMethod();
return 0;
}
五、Strategy Mode 策略模式
开放封闭原则
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。
策略模式其实是对算法的封装,当处理一个问题可能有多种算法(方法)时就可以使用该模式。Strategy类就是对该算法的封装,具体类则是对该算法的不同实现。
当程序中出现if…else…或者switch…case…,而且很有可能会增加分支时,一般就要策略模式了。
#include <iostream>
#include <string>
using namespace std;
class Strategy
{
public:
virtual ~Strategy() {
}
virtual void AlgorithmInterface() = 0;
};
//ConcreteStrategyA、ConcreteStrategyB对同一个算法的接口做了不同的实现
class ConcreteStrategyA : public Strategy
{
public:
virtual void AlgorithmInterface()
{
cout << "AlgorithmInterface Implemented by ConcreteStrategyA." << endl;
}
};
class ConcreteStrategyB : public Strategy
{
public:
virtual void AlgorithmInterface()
{
cout << "AlgorithmInterface Implemented by ConcreteStrategyB." << endl;
}
};
//Context代表上下文
class Context
{
public:
~Context()
{
delete m_Strategy;
}
Context(Strategy * pStrategy) : m_Strategy