1.设计模式是什么?
设计模式是指在软件开发过程中,经过验证的,用于解决在特定 环境下,重复 出现的,特定问题的解决方案。
软件设计过程中,解决问题的固定套路。
慎用设计模式。
2.设计模式是怎么来的?
满足设计原则后,慢慢迭代出来的。
3.设计模式解决了什么问题?
前提:具体的需求,既有稳定点,也有变化点。
期望只修改少量的代码,就可以适应需求的变化。
比喻:整洁的房间,有一只好动的猫,如何保持房间的整洁。答:将猫关在笼子里。
4.设计模式基础。
面对对象的思想。三大特征:封装、继承、多态。
封装:隐藏实现细节,实现模块化
继承:无需修改原有类的情况下,通过继承,实现对原有功能的拓展。
多态:静态多态,即函数重载;动态多态,指继承中虚函数重写。
设计原则:依赖倒置;开闭原则:对扩展开放对修改关闭;面向接口:针对封装和多态;封装变化点;单一职责;里氏替换;组合优于继承;最小知道原则。
5.如何学习设计模式?
明确目的:在现有设计模式的基础上,扩展代码;做功能抽象时,如何选择设计模式。
学习步骤:
该设计模式解决了什么问题:稳定点、变化点;该设计模式的结构是什么;符合哪些设计原则;如何在上面扩展代码;该设计模式有哪些典型应用场景:联系目前的工作场景,开源框架等。
模板方法:
定义一个操作中的算法的骨架 ,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
稳定点:算法的骨架;变化点:子流程需要变化。
代码结构:基类中有骨架流程接口;所有子流程对子类开放并且是虚函数;多态使用方式。
符合设计原则:单一职责;开闭原则;依赖倒置(子类扩展时,需要依赖基类的虚函数实现;使用者只依赖接口);封装变化点:protected;接口隔离;最小知道原则。
如何扩展:实现子类继承基类,复写子流程;通过多态调用方式使用。
示例代码:
cpp
#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;
}
protected:
bool expired;
// 对其他用户关闭,但是子类开放的
protected:
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 bool 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;
}
运行结果:
观察者模式:
定义:定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通 知并自动更新。
稳定点:"一"对"多"的依赖关系,"一"变化"多"跟着变化;变化点:"多"增加,"多"减少。
符合设计原则:面向接口编程、接口隔离(类与类依赖在一个接口)、封装变化点(attach,detach)。
如何扩展:继承实现接口,调用attach,调用detach
示例代码:
cpp
#include <list>
#include <algorithm>
#include <iostream>
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 << "DisplayD Show" << endl;
}
};
class WeatherData {
};
// 应对稳定点,抽象
// 应对变化点,扩展(继承和组合)
class DataCenter {
public:
void Attach(IDisplay* ob) {
obs.push_back(ob);
}
void Detach(IDisplay* ob) {
//
}
void Notify() {
float temper = CalcTemperature();
for (auto iter : obs) {
iter->Show(temper);
}
}
// 接口隔离
private:
WeatherData* GetWeatherData() {
WeatherData* wealthData = new WeatherData;
return wealthData;
}
float CalcTemperature() {
WeatherData* data = GetWeatherData();
// ...
float temper = 0;
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;
}
运算结果:
策略模式:
定义:定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。该模式使得算法可独立于使用它的客户程序而变化。
解决了什么问题:稳定点:客户程序与算法的调用关系;变化点:算法变化(新加算法、算法内容变化)。
设计原则:接口隔离(依赖注入、解决通过一个接口解决两个类的依赖);面向接口编程
示例代码:
cpp
class Context {
};
// 稳定点:抽象去解决它
// 变化点:扩展(继承和组合)去解决它
class ProStategy {
public:
virtual double CalcPro(const Context& ctx) = 0;
virtual ~ProStategy();
};
// cpp
class VAC_Spring : public ProStategy {
public:
virtual double CalcPro(const Context& ctx) {}
};
// cpp
class VAC_QiXi : public ProStategy {
public:
virtual double CalcPro(const Context& ctx) {}
};
class VAC_QiXi1 : public VAC_QiXi {
public:
virtual double CalcPro(const Context& ctx) {}
};
// cpp
class VAC_Wuyi : public ProStategy {
public:
virtual double CalcPro(const Context& ctx) {}
};
// cpp
class VAC_GuoQing : public ProStategy {
public:
virtual double CalcPro(const Context& ctx) {}
};
class VAC_Shengdan : public ProStategy {
public:
virtual double CalcPro(const Context& ctx) {}
};
class Promotion {
public:
Promotion(ProStategy* sss) : s(sss) {}
~Promotion() {}
double CalcPromotion(const Context& ctx) {
return s->CalcPro(ctx);
}
private:
ProStategy* s;
};
int main() {
Context ctx;
ProStategy* s = new VAC_QiXi1();
Promotion* p = new Promotion(s);
p->CalcPromotion(ctx);
return 0;
}