Linux c++学习第二章 创建型设计模式
设计模式的作用:
在实际开发过程中,会遇到很多各种各样的问题。需要用某些特定的套路去解决一类问题。保证代码的稳定。同时可以避免重复的工作。个人认为,类似于盖房子的设计图。
一、模版方法:
使用场景:某个品牌动物园,有一套固定流程,但是其中有若干个表演子流程可以创新替换,以尝试迭代更新表演流程。
要点:
1.最常用的设计模式,子类可以复写父类子流程,是父类骨架流程丰富。
2.反向控制流程的典型应用
3.父类proted保护子类需要复写的子流程,这样子类的子流程只能父类来调用。
本质:通过固定算法框架来约束子类的行为。
说人话:
父类把框架定好。在内部用protected关键字和虚函数来定义一个功能,也就是表演节目。但是不写具体表演什么。protected保证只有子类能复写,并且只能由父类来调用。虚函数保证了子类能重载该函数。
然后用子类继承父类。通过重载的方式把父类当中的虚函数做出具体的实现。就是爹说表演节目,儿子知道了以后,由儿子自己具体确定表演什么节目。其他儿子都通过继承加重载的方式来确定各自都要表演什么节目。这样弄后,父类就不需要改变了,让儿子改变就行。
每个儿子都写好后,通过父类指针,指向子类对象,就可以调用各个儿子准备的节目了。如果有新儿子表演新节目,直接继续创建儿子类,重载爹定下的表演节目即可。再创建爹指针,指向新儿子对象。
二、观察者模式
一对多,一变化,多也要变化。
场景举例:气象站发数据给数据中心,数据中心经过处理,将气象信息更新到多个不同的显示终端。
要点:
1.观察者模式使得我们可以独立地改变目标与观察者,从而使二者之间的关系送耦合。
2.观察者自己巨鼎是否订阅通知,目标对象并不关注有谁订阅。
3.观察者不要依赖通知顺序,目标对象也不知道通知顺序。
4。常用在基于事件的ui框架中,也是mvc的组成部分。
5.常用在分布式系统中、actor框架中。
代码:
#include <vector>
一如vector容器,用来存储所有终端。
//
class IDisplay {
定义出终端类,只定义显示功能(虚函数),不写具体的实现,由子类,也就是各种终端设备来实现。
public:
virtual void Show(float temperature) = 0;
virtual ~IDisplay() {}
};
定义子类终端A。负责自身功能的具体实现
class DisplayA : public IDisplay {
public:
virtual void Show(float temperature);
private:
void jianyi();
};
终端B
class DisplayB : public IDisplay{
public:
virtual void Show(float temperature);
};
终端C
class DisplayC : public IDisplay{
public:
virtual void Show(float temperature);
};
气象中心
class WeatherData {
};
数据中心
class DataCenter {
public:
定义出添加和删除终端的功能。public,用户可以使用这两个功能来添加活删除终端。
void Attach(IDisplay * ob);
void Detach(IDisplay * ob);
定义出显示功能。把所有添加的终端设备都加入到vector容器里面。当用户调用notify时,notify调用CalcTemperature();函数。从气象中心得到数据,计算数据并返回。然后依次把vector容器里的所有终端的show功能全部调用,把计算的数据(temper)输入进去。
void Notify() {
float temper = CalcTemperature();
for (auto iter = obs.begin(); iter != obs.end(); iter++) {
(*iter)->Show(temper);
}
}
// 接口隔离
从气象中心得到数据,然后计算数据。并且定义出vector容器
private:
virtual WeatherData * GetWeatherData();
virtual float CalcTemperature() {
WeatherData * data = GetWeatherData();
// ...
float temper/* = */;
return temper;
}
std::vector<IDisplay*> obs;
};
int main() {
创建数据中心。
DataCenter *center = new DataCenter;
创建终端A,b、c,用父类指针指向子类对象。
IDisplay *da = new DisplayA();
IDisplay *db = new DisplayB();
IDisplay *dc = new DisplayC();
abc加入数据中心
center->Attach(da);
center->Attach(db);
center->Attach(dc);
数据中心调用notify函数,把气象数据输入vector容器里的每个终端中。
center->Notify();
//-----
移除终端b
center->Detach(db);
在调用notify函数,此时终端b已经不存在。
center->Notify();
return 0;
}
三、策略模式
定义: 定义一系列算法,把它们封装起来,并且使它们可以互相替换。该模式使得算法独立于使用它的客户程序而变化。
背景:某商场节假日有固定促销活动,加大了促销力度,现在提升国庆节促销活动规格。
要点:
1.策略模式提供了一些列可重用的算法,从而使得类型在运行时方便地根据需要在各个算法之间进行切换。
2.策略模式消除了条件判断语句,也就是在解耦合
代码:
学会运用抽象 活动---活动策略----具体活动
定义出具体活动
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;
}
身为新手,不能机械性的记忆这些知识。应该了解一个大概,混个脸熟。然后在后面真的开发项目时使用这些设计模式,逐渐掌握。用的多了才能真正理解这些模式。个人认为
更多推荐



所有评论(0)