1.装饰器模式
在不改变现有类的基础上添加新的功能,属于结构型设计模式,作为现有类的一个包装。
Component为一个抽象对象,装饰器和具体需要被装饰的对象都继承自该抽象对象,最重要的一点是Decrator维护了一个需要被装饰的对象的引用,从而达到为该对象添加职能的目的。
代码实现:
为原始蛋糕加牛奶,加巧克力
#include <iostream>
//定义一个原始的抽象类蛋糕,装饰器的功能是给蛋糕加上各种装饰,如奶油,巧克力,瓜子仁,花生米等
//原始抽象类的蛋糕
class Cake
{
public:
virtual void showCake()=0;
virtual ~Cake(){};
std::string name;
};
//具体被装饰的对象,可以实例化
class ConcreteCake :public Cake
{
public:
ConcreteCake()
{
name = "原始蛋糕";
}
void showCake(){ std::cout << name.c_str() << std::endl; };
virtual ~ConcreteCake(){};
};
//装饰器类 维护一个需要被修饰的对象的引用
class CakeDecrator :public Cake
{
protected:
Cake* pCake; //维护一个Cake对象的引用,为Cake对象添加装饰
public:
virtual void showCake() = 0;
virtual ~CakeDecrator(){};
};
//具体添加了装饰的类
class CakeDecratorMilk : public CakeDecrator
{
public:
CakeDecratorMilk(Cake* pCake)
{
this->pCake = pCake;
}
void showCake()
{
this->name = pCake->name + "加奶油";
std::cout << name.c_str()<<std::endl;
};
virtual ~CakeDecratorMilk(){};
};
class CakeDecratorCholate : public CakeDecrator
{
public:
CakeDecratorCholate(Cake* pCake)
{
this->pCake = pCake;
}
void showCake()
{
this->name =pCake->name + "加巧克力";
std::cout << name.c_str() << std::endl;
};
virtual ~CakeDecratorCholate(){};
};
int main() {
ConcreteCake *pConCake = new ConcreteCake();
pConCake->showCake();
CakeDecratorMilk* pDecMilk = new CakeDecratorMilk(pConCake);
pDecMilk->showCake();
CakeDecratorCholate *pDecCho = new CakeDecratorCholate(pDecMilk);
pDecCho->showCake();
delete pConCake;
delete pDecMilk;
delete pDecCho;
return 0;
}
2.MVC设计模式
MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)。
MVC分为三层
-
最上面的一层,是直接面向最终用户的"视图层"(View)。它是提供给用户的操作界面,是程序的外壳。
-
最底下的一层,是核心的"数据层"(Model),也就是程序需要操作的数据或信息。
-
中间的一层,就是"控制层"(Controller),它负责根据用户从"视图层"输入的指令,选取"数据层"中的数据,然后对其进行相应的操作,产生最终结果。
使用者只能接触到View曾和Controler层,Model层对于用户是隐藏的。
使用三层架构的目的:解耦。
【优点】
开发人员可以只关注整个结构中的其中某一层;
可维护性高,可扩展性高
可以降低层与层之间的依赖;
有利于标准化;
利于各层逻辑的复用
【缺点】
降低了系统的性能。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成
有时会导致级联的修改,这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码
开发成本增加
3.单例模式
单例模式定义:
保证一个类只有一个实例,并提供一个访问它的全局访问点。首先,需要保证一个类只有一个实例;在类中,要构造一个实例,就必须调用类的构造函数,如此,为了防止在外部调用类的构造函数而构造实例,需要将构造函数的访问权限标记为protected或private;最后,需要提供要给全局访问点,就需要在类中定义一个static函数,返回在类内部唯一构造的实例。
为保证线程安全,具有以下几种单例模式的实现:
1.双检测加锁模式
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton *GetInstance()
{
if (m_Instance == NULL )
{
Lock(); // Lock操作,此处仅为了说明
if (m_Instance == NULL )
{
m_Instance = new Singleton ();
}
UnLock(); // lock操作,此处仅为了说明
}
return m_Instance;
}
static void DestoryInstance()
{
if (m_Instance != NULL )
{
delete m_Instance;
m_Instance = NULL ;
}
}
int GetTest()
{
return m_Test;
}
private:
Singleton(){ m_Test = 0; }
static Singleton *m_Instance;
int m_Test;
};
Singleton *Singleton ::m_Instance = NULL;
int main(int argc , char *argv [])
{
Singleton *singletonObj = Singleton ::GetInstance();
cout<<singletonObj->GetTest()<<endl;
Singleton ::DestoryInstance();
return 0;
}
2.使用静态初始化
在主线程中初始化该类的单例,保证其他线程无法再初始化该单例。
分为懒汉式初始化和饿汉式初始化
- 程序被加载时立即进行的初始化。这个初始化发生在main函数之前。即使程序任何地方都没访问过该变量, 仍然会进行初始化,因此形象地称之为"饿汉式初始化"。
- 这个初始化发生在变量第一次被引用。也就是说,从程序执行模型角度看,程序所在进程空间中,哪个线程先访问了这个变量,就是哪个线程来初始化这个变量。因此,相对于加载初始化来说,这种初始化是把真正的初始化动作推迟到第一次被访问时,因而形象地称为"懒汉式初始化"。
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton *GetInstance()
{
return const_cast <Singleton *>(m_Instance);
}
static void DestoryInstance()
{
if (m_Instance != NULL )
{
delete m_Instance;
m_Instance = NULL ;
}
}
int GetTest()
{
return m_Test;
}
private:
Singleton(){ m_Test = 10; }
static const Singleton *m_Instance;
int m_Test;
};
const Singleton *Singleton ::m_Instance = new Singleton();
int main(int argc , char *argv [])
{
Singleton *singletonObj = Singleton ::GetInstance();
cout<<singletonObj->GetTest()<<endl;
Singleton ::DestoryInstance();
}
3.资源获取即初始化方法自动析构实例
SIngleton类中,静态初始化了一个GC类,该GC类在程序退出时自动析构,该实例析构时自动析构单例。
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton *GetInstance()
{
return m_Instance;
}
int GetTest()
{
return m_Test;
}
private:
Singleton(){ m_Test = 10; }
static Singleton *m_Instance;
int m_Test;
// This is important
class GC
{
public :
~GC()
{
// We can destory all the resouce here, eg:db connector, file handle and so on
if (m_Instance != NULL )
{
cout<< "Here is the test" <<endl;
delete m_Instance;
m_Instance = NULL ;
}
}
};
static GC gc;
};
Singleton *Singleton ::m_Instance = new Singleton();
Singleton ::GC Singleton ::gc;
int main(int argc , char *argv [])
{
Singleton *singletonObj = Singleton ::GetInstance();
cout<<singletonObj->GetTest()<<endl;
return 0;
}
4.工厂模式
参考文献>>
分为三种方案
1.简单工厂模式:可以理解为只有一个工厂,且该工厂可产生多个实例的模式。
首先最顶层是一个抽象类,然后通过创建子类来决定这个类具体是什么内容,然后创建一个抽象工厂类,这个工厂类可以生产不同子类子类的对象。以生产手机为例,首先创建一个生产的规范,规定手机的生产过程,然后创建子类,来决定要生产什么品牌的手机,最后创建工厂类,来生产不同品牌的手机。
2.工厂方法模式:可以理解为有多个工厂,且每个工厂只生产一个实例的模式。
以制造手机为例,首先,与简单工厂相同,先创建一个抽象手机类型,然后还是创建子类来决定具体的类型,然后创建抽象工厂类,抽象工厂类提供抽象的加工方法,然后创建子类类决定具体是哪种手机的工厂,每个工厂只能生产一个实例。
3.抽象工厂模式:可以理解为有多个工厂,且每个工程科生产多个实例的模式。
相比于工厂模式,以同时制造手机、平板为例,首先创建手机、平板的抽象类,然后创建子类来决定具体是什么品牌的手机或平板,然后在抽象工厂中添加制造手机、平板的接口,在具体工厂中来决定具体制造哪种品牌的产品。即有多个工厂,比如手机工厂、平板工厂,手机工厂生产哪个品牌的,平板工厂生产哪个品牌的。
5.建造者模式
- 建造者模式和工厂模式使用很相似,但也有区别,建造者模式最主要功能是基本方法的调用顺序安排,也就是这些基本方法已经实现了;而工厂方法则重点是创建,你要什么对象我创造一个对象出来,组装顺序则不是他关心的。
- 建造者模式使用的场景,一是产品类非常的复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式是非常合适。
参考文章>>
参考文章>>
建造者模式的定义将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示(DP)
例子:
对于客户来说,只需知道导向者就可以了,通过导向者,客户就能构造复杂的对象,而不需要知道具体的构造过程。下面给出小人例子的代码实现。
class Builder
{
public:
virtual void BuildHead() {}
virtual void BuildBody() {}
virtual void BuildLeftArm(){}
virtual void BuildRightArm() {}
virtual void BuildLeftLeg() {}
virtual void BuildRightLeg() {}
};
//构造瘦人
class ThinBuilder : public Builder
{
public:
void BuildHead() { cout<<"build thin body"<<endl; }
void BuildBody() { cout<<"build thin head"<<endl; }
void BuildLeftArm() { cout<<"build thin leftarm"<<endl; }
void BuildRightArm() { cout<<"build thin rightarm"<<endl; }
void BuildLeftLeg() { cout<<"build thin leftleg"<<endl; }
void BuildRightLeg() { cout<<"build thin rightleg"<<endl; }
};
//构造胖人
class FatBuilder : public Builder
{
public:
void BuildHead() { cout<<"build fat body"<<endl; }
void BuildBody() { cout<<"build fat head"<<endl; }
void BuildLeftArm() { cout<<"build fat leftarm"<<endl; }
void BuildRightArm() { cout<<"build fat rightarm"<<endl; }
void BuildLeftLeg() { cout<<"build fat leftleg"<<endl; }
void BuildRightLeg() { cout<<"build fat rightleg"<<endl; }
};
//构造的指挥官
class Director
{
private:
Builder *m_pBuilder;
public:
Director(Builder *builder) { m_pBuilder = builder; }
void Create(){
m_pBuilder->BuildHead();
m_pBuilder->BuildBody();
m_pBuilder->BuildLeftArm();
m_pBuilder->BuildRightArm();
m_pBuilder->BuildLeftLeg();
m_pBuilder->BuildRightLeg();
}
};
客户的使用方式:
int main()
{
FatBuilder thin;
Director director(&thin);
director.Create();
return 0;