设计模式:创建型
说明:本文内容主要摘自www.0voice.com课程内容
设计模式定义
设计模式是指在软件开发中,经过验证的,用于解决在特定环境下,重复出现的,特定问题的解决方案
如何学习设计模式?
- 找到稳定点和变化点,把变化点隔离出来(解耦合-把耦合限定在最小范围)
- 先满足设计原则,慢慢迭代出设计模式(分治思维)
设计原则
依赖倒置
- 高层模块不应该依赖低层模块,两者都应该依赖抽象;
- 抽象不应该依赖具体实现,具体实现应该依赖于抽象;
High level modules should not depend upon low level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
– Robert C.Martin
自动驾驶系统作为高层不应依赖于底层的具体汽车厂商,而应该抽象出一个自动驾驶标准,让高层和低层模块都依赖于它;同时自动驾驶系统、汽车生产厂商都是具体实现,它们应该都依赖自动驾驶行业标准(抽象)。
开放封闭
一个类应该对扩展开放,对修改关闭。
类的直接组合和继承增强了类之间的耦合。应使用的拓展方法:对于C++,尽可能组合类的指针,而不是类本身(晚绑定/动态绑定);或者使用虚函数进行继承。
面向接口
客户程序应该只知道对象接口,而不需要知道对象的具体数据类型
封装变化点
将稳定点和变化点分离,扩展修改变化点;让稳定点和变化点的实现层次分离
单一职责
一个类应该仅有一个引起它变化的原因
理氏替换
子类型必须能够替换掉它的父类型,具体地说就是,子类覆盖父类时必须要实现父类的原则;
接口隔离
不应该强迫客户依赖于它们不用的方法;
一般用于处理一个类拥有比较多的接口,而这些接口涉及到很多职责。
组合优于继承
继承耦合度高,组合耦合度低
原则的层次关系
优先满足这四个原则:
- 开放封闭(最优先)
- 单一职责
- 理氏替换
- 接口隔离
后面三个间接地佐证开闭原则:单一职责->修改封闭;理氏替换->扩展开放;接口隔离->减少修改
根据这四个原则,慢慢地就能推导出设计模式。
模板方法
定义
定义一个操作中的算法的骨架 ,而将一些步骤的实现延迟到子类中。 Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 ——《 设计模式》 GoF
要点
- 最常用的设计模式,子类可以复写父类子流程,使父类的骨架流程丰富;
- 反向控制流程的典型应用(父类流程控制子类流程);
- 父类 protected 保护子类需要复写的子流程;这样子类的子流程只能父类来调用。
举例
某个品牌动物园,有一套固定的表演流程,但是其中有若干个表演子流程可创新替换,以尝试迭代更新表演流程
这里头一套固定的表演流程就是算法(父类)的骨架(固定点),而若干个表演子流程(变化点)就是父类的一些可以复写的方法。
本质
通过固定算法骨架来约束子类的行为。
结构图
代码示例
对于上面提到的动物园表演流程实现代码,这里有一个不好的例子:
class ZooShow {
public:
ZooShow(int type = 1) : _type(type) {
}
public:
void Show() {
Show0();
Show1();
Show2();
Show3();
}
private:
void Show0() {
cout << _type << " show0" << endl;
}
void Show1() {
if (_type == 1) {
cout << _type << " Show1" << endl;
} else if (_type == 2) {
cout << _type << " Show1" << endl;
} else if (_type == 3) {
}
}
void Show2() {
if (_type