设计模式依托于设计原则,最主要的是设计原则的理解,在设计模式中理解原则,使用原则尤为重要。模式设计原则:
- 依赖倒置原则:
- 高层模块不应该依赖低层模块,两者都应该依赖抽象
- 抽象不应该依赖具体实现,具体实现应该依赖于抽象
- 开发封闭原则:
- 一个类应该对扩展开发,对修改关闭
- 面向接口编程:
- 不将变量类型声明为某个特定的具体类,⽽是声明为某个接⼝。
- 客户程序⽆需获知对象的具体类型,只需要知道对象所具有的接⼝。
- 减少系统中各部分的依赖关系,从⽽实现“⾼内聚、松耦合”的类型设计⽅案
- 封装变化点:
- 将稳定点和变化点分离,扩展变化点;让稳定点与变化点实现层次分离。
- 单一职责原则:
- 一个类应该仅有一个引起它变化的原因
- 里式替换原则:
- ⼦类型必须能够替换掉它的⽗类型;主要出现在⼦类覆盖⽗类实现,原来使⽤⽗类型的程序可能出现错误;覆盖了⽗类⽅法却没实现⽗类⽅法的职责;
- 接口隔离原则:
- 不应该强迫客户依赖于他们不⽤的⽅法;
- ⼀般⽤于处理⼀个类拥有⽐较多的接⼝,⽽这些接⼝涉及到很多职责;
- 对象组合优于类继承
- 继承耦合度高,组合耦合度低
-
定义
定义⼀个操作中的算法的⻣架 ,⽽将⼀些步骤延迟到⼦类中。 Template Method使得⼦类可以不改变⼀个算法的结构即可重定义该算法的某些特定步骤。 ——《 设计模式》 GoF
-
背景
某个品牌动物园,有⼀套固定的表演流程,但是其中有若⼲个表演⼦流程受欢迎程度⽐较低,希望将这⼏个表演流程创新,以尝试迭代更新表演流程;
-
代码
class ZooShow{
public:
void show(){//该类的职责,也是固定点
show0();
show1();
show2();
show3();
}
protected://变化点,且接口分离原则,不能提供给客户他们不需要的接口
virtual void show0(){
cout << "show0()" << endl;
};
virtual void show1(){
};
virtual void show2(){
cout << "show2()" << endl;
};
virtual void show3(){
};
};
class ZooShowEs
:public ZoomShow
{
public:
virtual void show1(){
cout << "ZoomShowEs::show1()" << endl;
}
virtual void show3(){
cout << "ZoomShowEs::show1()" << endl;
};
};
//反向调用:子类继承父类接口实现功能,最终父类去调用子类的函数
//此时高层即main函数中的流程,低层就是父类和子类,就是依赖倒置原则
int main(){
ZooShow * p = new ZooShowEs();
p->show();
}在这里插入代码片
-
要点
⾮常常⽤的设计模式,⼦类可以复写⽗类的⼦流程,使⽗类的⼤流程更丰富;反向控制流程的典型应⽤;⽗类 protected 保护⼦类需要复写的⼦流程;这样⼦类的⼦流程只能⽗类来调⽤;充分体现了依赖倒置原则;
-
本质
通过固定算法⻣架来约束⼦类的⾏为;
-
结构图
-
定义
定义对象间的⼀种⼀对多(变化)的依赖关系,以便当⼀个对象(Subject)的状态发⽣改变时,所有依赖于它的对象都得到通知并⾃动更新。 ——《 设计模式》 GoF
-
背景
⽓象站发布⽓象资料给数据中⼼,数据中⼼经过处理,将⽓象信息更新到两个不同的显示终端(A 和B);
-
代码
class DisplayA{
public:
void Show(float temperature);
};
class DisplayB{
void Show(float temperature);
};
class WeatherData{
};
class DataCenter{
public:
float CalcTemperature(){
WeatherData * data = GetWeatherData();
//...
float temper;
return temper;
}
private:
WeatherData * GetWeatherData();
};
int main(){
DataCenter *center = new DataCenter;
DisplayA *da = new DisplayA();
DisplayB *db = new DisplayB();
float temper = center->CalcTemperture();
da->Show(temper);
db->Show(temper);
}
class IDisplay{
virtual void Show(float temperature) = 0;
};
class DisplayA
:public IDisplay
{
public:
void Show(float temperature){
cout << "DisplayA::Show()" << endl;
}
};
class DisplayB
:public IDisplay
{
void Show(float temperature){
cout << "DisplayB::Show()" << endl;
}
};
class WeatherData{
};
class DataCenter{
public:
void Show(){
CalcTemperature();
for(auto iter = vec.begin();iter != vec.end(); ++iter){
(*iter)->Show();
}
}
void Attache(IDisplay* p);
void Dttache(IDisplay* p);
protected://接口隔离原则,但其子类任然能够进行修改
virtual float CalcTemperature(){
WeatherData * data = GetWeatherData();
//...
float temper;
return temper;
}
private:
vector vec;
WeatherData * GetWeatherData();
};
int main(){
DataCenter *center = new DataCenter;
IDisplay *da = new DisplayA();
IDisplay *db = new DisplayB();
cecter->Attache(da);
cecter->Attache(da);
center->Show();
}在这里插入代码片
-
要点
观察者模式使得我们可以独⽴地改变⽬标与观察者,从⽽使⼆者之间的关系松耦合;观察者⾃⼰决定是否订阅通知,⽬标对象并不关注谁订阅了;观察者不要依赖通知顺序,⽬标对象也不知道通知顺序;常使⽤在基于事件的ui框架中,也是MVC的组成部分;常使⽤在分布式系统中,actor框架中;
-
本质
触发联动;
-
结构图



