目录
一、前言
问题一:如何学习设计模式?
- 先了解设计原则,设计模式是开发者在开发过程中从多种开发原则中组合变换总结出的设计方案。
- 明确每个设计模式中的稳定点和变化点,即我们每次应用设计模式写代码时在不同场景下代码结构中的不变点和变化点。
- 明确使用某种设计模式的目的
- 在做功能抽象是,如何选择设计模式?
- 在现有的设计模式上如何扩展代码?
问题二:在学习设计模式时,需要明确哪些问题?
- 这一设计模式解决了什么问题?(why)//找到稳定点和变化点
- 这一设计模式的代码结构是什么?(what)//快速判定设计模式的种类
- 符合哪些设计原则?
- 如何在原有的设计模式上扩展代码?//找到变化点->扩展代码
- 该设计模式有哪些典型的应用场景?//工作场景或者开源框架->理解学习并进行知识迁移
二、设计模式的基础
1.首先了解类模型、类关系(封装、继承、友元、多态)
设计模式多用到组合基类指针的方式设计接口
2.设计原则
- 依赖倒置
简单来说就是抽象出接口,使用者只依赖接口,派生类依赖基类的虚函数实现
- 开放封闭
对扩展(组合和继承)开放,对修改封闭
- 面向接口
不将变量类型声明为某个特定的具体类,而是声明为某个接口
- 封装变化点
将稳定点和变化点分离,扩展修改变化点
- 单一职责
一个类应该仅有一个引起它变化的原因
- 里氏替换
子类覆盖父类的实现,重写基类非抽象类方法
- 接口隔离
一般用于处理一个类拥有比较多的接口,而这些接口涉及到很多职责;客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。
- 组合优于继承
继承耦合度高,组合耦合度低
三、常用的设计模式
1.模板方法
稳定点:结构骨架
变化点:在不改变算法结构而自定义算法的流程
快速识别点:基类中用protected封装函数功能,派生类继承并重写函数
例:原代码示例
#include <iostream>
using namespace std;
// 设计原则
// 1. 设计原则演变过来的 2.符合设计原则的代码,只需要修改少量代码就可以演变成设计模式
// 接口隔离原则 1. 类封装 权限限定词来实现 2. 类与类依赖 接口(依赖注入)
// 最小知道原则
// 破坏了哪些设计原则:
// 单一职责(变化方向) 封装
// 开闭原则 对扩展开放 对修改关闭
// 扩展方式:继承,多态组合
class ZooShow {
public:
ZooShow(int type = 1) : _type(type) {}//构造函数
public:
void Show() {
if (Show0())
PlayGame();
Show1();
Show2();
Show3();
}
private:
void PlayGame() {
cout << "after Show0, then play game" << endl;
}
bool Show0() {
if (_type == 1) {
//
return true;
} else if (_type == 2 ) {
// ...
} else if (_type == 3) {
}
cout << _type << " show0" << endl;
return true;
}
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 == 20) {
}
cout << "base Show2" << endl;
}
void Show3() {
if (_type == 1) {
cout << _type << " Show1" << endl;
} else if (_type == 2) {
cout << _type << " Show1" << endl;
}
}
private:
int _type;
};
int main () {
ZooShow *zs = new ZooShow(1);
zs->Show();
return 0;
}
采用模板方法设计模式后的代码示例
#include <iostream>
using namespace std;
// 开闭
class ZooShow {//单一职责
public:
void Show() {
// 如果子表演流程没有超时的话,进行一个中场游戏环节;如果超时,直接进入下一个子表演流程
if (Show0())
PlayGame();
Show1();
Show2();
Show3();
}
private:
void PlayGame() {
cout << "after Show0, then play game" << endl;
}
bool expired;
// 对其他用户关闭,但是子类开放的
protected://protect中是可以让子类进行复写的一些接口
virtual bool Show0() {
cout << "show0" << endl;
if (! expired) {
return true;
}
return false;
}
virtual void Show2() {
cout << "show2" << endl;
}
virtual void Show1() {
}
virtual void Show3() {
}
};
// 框架
// 模板方法模式
class ZooShowEx10 : public ZooShow {
protected:
virtual void Show0() {
if (! expired) {
return true;
}
return false;
}
}
class ZooShowEx1 : public ZooShow {
protected:
virtual bool Show0() {
cout << "ZooShowEx1 show0" << endl;
if (! expired) { // 里氏替换
return true;
}
return false;
}
virtual void Show2(){
cout << "show3" << endl;
}
};
class ZooShowEx2 : public ZooShow {
protected:
virtual void Show1(){
cout << "show1" << endl;
}
virtual void Show2(){
cout << "show3" << endl;
}
};
class ZooShowEx3 : public ZooShow {
protected:
virtual void Show1(){
cout << "show1" << endl;
}
virtual void Show3(){
cout << "show3" << endl;
}
virtual void Show4() {
//
}
};
/*
*/
int main () {
ZooShow *zs = new ZooShowEx10; // 晚绑定还是早绑定
// ZooShow *zs1 = new ZooShowEx1;
// ZooShow *zs2 = new ZooShowEx2;
zs->Show();//最小知道原则
return 0;
}
2.观察者模式
稳定点:“一”——数据中心
变化点:“多”——显示终端的增加和减少
快速识别点:一变化多跟着变化
例:原代码示例
class DisplayA {
public:
void Show(float temperature);
};
class DisplayB {
public:
void Show(float temperature);
};
class DisplayC {
public:
void Show(float temperature);
};
class WeatherData {
};
class DataCenter {
public:
void TempNotify() {
DisplayA *da = new DisplayA;
DisplayB *db = new DisplayB;
DisplayC *dc = new DisplayC;
// DisplayD *dd = new DisplayD;
float temper = this->CalcTemperature();
da->Show(temper);
db->Show(temper);
dc->Show(temper);
dc->Show(temper);
}
private:
float CalcTemperature() {
WeatherData * data = GetWeatherData();
// ...
float temper/* = */;
return temper;
}
WeatherData * GetWeatherData(); // 不同的方式
};
int main() {
DataCenter *center = new DataCenter;
center->TempNotify();
return 0;
}
采用观察者设计模式后的代码示例:
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
//
class IDisplay {
public:
virtual void Show(float temperature) = 0;
virtual ~IDisplay() {}
};
class DisplayA : public IDisplay {
public:
virtual void Show(float temperature) {
cout << "DisplayA Show" << endl;
}
private:
void jianyi();
};
class DisplayB : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayB Show" << endl;
}
};
class DisplayC : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayC Show" << endl;
}
};
class DisplayD : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayC Show" << endl;
}
};
class WeatherData {
};
// 应对稳定点,抽象
// 应对变化点,扩展(继承和组合)
class DataCenter {//稳定点
public:
void Attach(IDisplay * ob) {
//
}
void Detach(IDisplay * ob) {
//
}
void Notify() {
float temper = CalcTemperature();
for (auto &ob : obs) {
ob->Show(temper);
}
}
// 接口隔离
private:
WeatherData * GetWeatherData();
float CalcTemperature() {
WeatherData * data = GetWeatherData();
// ...
float temper/* = */;
return temper;
}
std::list<IDisplay*> obs;//接口隔离,解耦合
};
int main() {
// 单例模式
DataCenter *center = new DataCenter;
// ... 某个模块
IDisplay *da = new DisplayA();
center->Attach(da);
// ...
IDisplay *db = new DisplayB();
center->Attach(db);
IDisplay *dc = new DisplayC();
center->Attach(dc);
center->Notify();
//-----
center->Detach(db);
center->Notify();
center->Attach(dd);
center->Notify();
return 0;
}
3.策略模式
例:原代码示例:
class DisplayA {
public:
void Show(float temperature);
};
class DisplayB {
public:
void Show(float temperature);
};
class DisplayC {
public:
void Show(float temperature);
};
class WeatherData {
};
class DataCenter {
public:
void TempNotify() {
DisplayA *da = new DisplayA;
DisplayB *db = new DisplayB;
DisplayC *dc = new DisplayC;
// DisplayD *dd = new DisplayD;
float temper = this->CalcTemperature();
da->Show(temper);
db->Show(temper);
dc->Show(temper);
dc->Show(temper);
}
private:
float CalcTemperature() {
WeatherData * data = GetWeatherData();
// ...
float temper/* = */;
return temper;
}
WeatherData * GetWeatherData(); // 不同的方式
};
int main() {
DataCenter *center = new DataCenter;
center->TempNotify();
return 0;
}
采用策略设计模式后的代码示例:
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
//
class IDisplay {
public:
virtual void Show(float temperature) = 0;
virtual ~IDisplay() {}
};
class DisplayA : public IDisplay {
public:
virtual void Show(float temperature) {
cout << "DisplayA Show" << endl;
}
private:
void jianyi();
};
class DisplayB : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayB Show" << endl;
}
};
class DisplayC : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayC Show" << endl;
}
};
class DisplayD : public IDisplay{
public:
virtual void Show(float temperature) {
cout << "DisplayC Show" << endl;
}
};
class WeatherData {
};
// 应对稳定点,抽象
// 应对变化点,扩展(继承和组合)
class DataCenter {//稳定点
public:
void Attach(IDisplay * ob) {
//
}
void Detach(IDisplay * ob) {
//
}
void Notify() {
float temper = CalcTemperature();
for (auto &ob : obs) {
ob->Show(temper);
}
}
// 接口隔离
private:
WeatherData * GetWeatherData();
float CalcTemperature() {
WeatherData * data = GetWeatherData();
// ...
float temper/* = */;
return temper;
}
std::list<IDisplay*> obs;//接口隔离,解耦合
};
int main() {
// 单例模式
DataCenter *center = new DataCenter;
// ... 某个模块
IDisplay *da = new DisplayA();
center->Attach(da);
// ...
IDisplay *db = new DisplayB();
center->Attach(db);
IDisplay *dc = new DisplayC();
center->Attach(dc);
center->Notify();
//-----
center->Detach(db);
center->Notify();
center->Attach(dd);
center->Notify();
return 0;
}