设计模式
总结一些平时用得比较多的设计模式
代理模式
是一种结构型模式
代理模式 Proxy 模式
客户(实际对象) -> 助理Proxy(代理类) ->老板(委托类)
即委托类通过代理类来控制实际对象的访问权限
#include<iostream>
#include<memory>
using namespace std;
//基类
class Video{
public:
virtual void showCommon() = 0;
virtual void showVIP() = 0;
virtual void showTicket() = 0;
};
//委托类
class CoshVideo : public Video{
public:
virtual void showCommon(){
cout<<"Cosh : Common"<<endl;
};
virtual void showVIP(){
cout<<"Cosh : VIP"<<endl;
};
virtual void showTicket(){
cout<<"Cosh : Ticket"<<endl;
};
};
//代理类1
class CommonUser : public Video{
public:
CommonUser(){base = new CoshVideo();}
~CommonUser(){delete base;}
virtual void showCommon(){
base->showCommon();
};
virtual void showVIP(){
cout<<"Common : VIP Banned"<<endl;
};
virtual void showTicket(){
cout<<"Common : Ticket Banned"<<endl;
};
private:
Video* base;
};
//代理类2
class VIPUser : public Video{
public:
VIPUser(){base = new CoshVideo();}
~VIPUser(){delete base;}
virtual void showCommon(){
base->showCommon();
};
virtual void showVIP(){
base->showVIP();
};
virtual void showTicket(){
cout<<"VIP : Ticket Banned"<<endl;
};
private:
Video* base;
};
//代理类3
class TicketUser : public Video{
public:
TicketUser(){base = new CoshVideo();}
~TicketUser(){delete base;}
virtual void showCommon(){
base->showCommon();
};
virtual void showVIP(){
base->showVIP();
};
virtual void showTicket(){
base->showTicket();
};
private:
Video* base;
};
void show(std::unique_ptr<Video> &p){
p->showCommon();
p->showVIP();
p->showTicket();
cout<<endl;
}
signed main(){
// unique_ptr<Video> user(new CommonUser());
std::unique_ptr<Video> common(new CommonUser());
std::unique_ptr<Video> VIP(new VIPUser());
std::unique_ptr<Video> ticket(new TicketUser());
show(common);
show(VIP);
show(ticket);
return 0;
}
单例模式
一个类不管创建多少次对象,永远只能得到该类型的一个对象的实例
使用情景:日志模块,数据库模式
饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了(一定是线程安全的)
懒汉式单例模式:唯一的实例对象,第一次 获取它时才产生(会有线程安全问题,可避免)
一般情况下,由于单例模式的初始化会有大量读取文件IO,或者加载配置的代码
所以懒汉式单例模式更受到青睐
使用单例模式时,记得delete掉拷贝函数和赋值运算符重载
饿汉式单例模式:
class Singleton{
public:
static Singleton* getSingleton(){ //#3 后去类的唯一实例对象的接口方法
return &instance;
}
static void get(){
std::cout<<id<<std::endl;
}
private:
static Singleton* instance; //#2 定义一个唯一的类的实例对象
static const int id = 10;
Singleton(){ //#1 构造函数私有化
}
Singleton& operator= (const Singleton& a) = delete;
Singleton(const Singleton& a) = delete;
};
Singleton Singleton::instance; //在编译的时候已经构造出了对象
signed main(){
Singleton* s1 = Singleton::getSingleton();
Singleton* s2 = Singleton::getSingleton();
Singleton* s3 = Singleton::getSingleton();
s1->get();
s2->get();
s3->get();
}
懒汉式单例模式
//利用互斥锁构造函数对象
mutex mtx;
class Singleton{
public:
static Singleton* getSingleton(){ //#3 后去类的唯一实例对象的接口方法
if(instance == nullptr){
lock_guard<std::mutex> lck(mtx);
if(instance == nullptr){
Singleton();
}
}
return instance;
}
private:
static Singleton* instance; //#2 定义一个唯一的类的实例对象
static const int id = 10;
Singleton(){ //#1 构造函数私有化
}
Singleton& operator= (const Singleton& a) = delete;
Singleton(const Singleton& a) = delete;
};
在该情况下记得使用双重判定,否则仍可能导致线程安全问题
//利用编译static时,编译器会自动对static静态成员上锁的特性构造
#include<iostream>
#include<mutex>
#include<thread>
using namespace std;
mutex mtx;
class Singleton{
public:
static Singleton* getSingleton(){ //#3 后去类的唯一实例对象的接口方法
// 函数静态局部,在函数第一次访问静态资源时才会被使用
static Singleton instance; //#2 定义一个唯一的类的实例对象
return &instance;
}
private:
static const int id = 10;
Singleton(){ //#1 构造函数私有化
}
Singleton& operator= (const Singleton& a) = delete;
Singleton(const Singleton& a) = delete;
};
signed main(){
Singleton* s1 = Singleton::getSingleton();
Singleton* s2 = Singleton::getSingleton();
}
观察者模式
是一种行为型模式
行为型模式:主要关注的是对象之间的通信
观察者-监听者模式(发布-订阅模式)设计模式:主要是关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变的时候,其他对象都能够接收到相对应的通知
一组数据(数据对象) ->通过这一组数据 ->曲线图(对象1)/柱状图(对象2)/圆饼图(对象3)
当数据对象改变时,对象1,对象2,对象3应该及时地收到相对应的通知并改变自身状态
Observe1 Observer2 Observe3
subject(主题) , 当主题有更改时,应该及时通知相应的观察者,去处理相应的事件
#include<iostream>
#include<memory>
#include<unordered_map>
#include<list>
using namespace std;
//观察者抽象类
class Observer
{
public:
// 处理消息的接口
virtual void handleMessage(int msgid) = 0;
};
class Observer1 : public Observer
{
public:
Observer1(int id):id(id){}
// 处理消息的接口
virtual void handleMessage(int msgid){
switch (msgid)
{
case 1:
cout<<id<<": call back Message1"<<endl;
break;
case 2:
cout<<id<<": call back Message2"<<endl;
break;
default:
break;
}
}
private:
int id;
};
class Observer2 : public Observer
{
public:
Observer2(int id):id(id){}
// 处理消息的接口
virtual void handleMessage(int msgid){
switch (msgid)
{
case 1:
cout<<id<<": call back Message1"<<endl;
break;
case 3:
cout<<id<<": call back Message3"<<endl;
break;
default:
break;
}
}
private:
int id;
};
class Observer3 : public Observer
{
public:
Observer3(int id):id(id){}
// 处理消息的接口
virtual void handleMessage(int msgid){
switch (msgid)
{
case 2:
cout<<id<<": call back Message2"<<endl;
break;
case 3:
cout<<id<<": call back Message3"<<endl;
break;
default:
break;
}
}
private:
int id;
};
class Subject{
public:
void addObserver(Observer* observer ,int msgid){
m[msgid].push_back(observer);
}
void dispatch(int msgid){
for(auto it : m[msgid])
{
it->handleMessage(msgid);
}
}
private:
unordered_map<int , list<Observer*>> m;
};
signed main(){
Subject sub1;
Observer *ob1 = new Observer1(1);
Observer *ob2 = new Observer2(2);
Observer *ob3 = new Observer3(3);
sub1.addObserver(ob1 , 1);
sub1.addObserver(ob1 , 2);
sub1.addObserver(ob2 , 1);
sub1.addObserver(ob2 , 3);
sub1.addObserver(ob3 , 2);
sub1.addObserver(ob3 , 3);
for(;;){
int a;
cout<<"enter : ";
cin>>a;
if(a == -1) break;
sub1.dispatch(a);
}
delete ob1;
delete ob2;
delete ob3;
return 0;
}
工厂模式
简单工厂 :Simple Factory
工厂方法 : Factory Method
抽象工厂: Abstract Factory
工厂模式:主要是封装了对象的创建
简单工厂
把对象的创建封装在一个接口函数里面,通过传入不同的标识,返回创建的对象
客户不用负责new对象,不用了解对象创建的详细过程
提供创建对象实例的接口函数不闭合,不能对修改关闭
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class Car
{
public:
Car(string name):_name(name){}
virtual void show() = 0;
protected:
string _name;
};
class Bmw : public Car
{
public:
Bmw(string name) :Car(name){}
void show(){
cout<<"Got a new BWM"<<endl;
}
};
class Audi : public Car
{
public:
Audi(string name) :Car(name){}
void show(){
cout<<"Got a new Audi"<<endl;
}
};
enum CarType{
BMW , AUDI
};
//
class simpleFactory{
public:
//不满足开闭原则,逻辑会出现问题
Car* createCar(CarType ct){
switch (ct)
{
case BMW:
return new Bmw("X1");
break;
case AUDI:
return new Audi("A6");
break;
default:
cerr<<"post error"<<endl;
break;
}
}
};
signed main(){
unique_ptr<simpleFactory> factory(new simpleFactory()) ;
unique_ptr<Car> p1(factory->createCar(BMW));
unique_ptr<Car> p2(factory->createCar(AUDI));
p1->show() , p2->show();
return 0;
}
工厂方法
定义了一个Factory积累,提供了一个纯虚函数(创产品),定义派生类(具体产品的工厂)负责对应的产品,可以做到不同的产品,在不用的工厂里面创建,能够对现有工厂,以及产品的修改的关闭
实际上,很多产品是有关联关系的,属于一个产品簇,不应该放在不同的工厂里面去创建
一是:不符合实际的产品对象创建逻辑
二是:工厂类太多了,不好维护
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class Car
{
public:
Car(string name):_name(name){}
virtual void show() = 0;
protected:
string _name;
};
class Bmw : public Car
{
public:
Bmw(string name) :Car(name){}
void show(){
cout<<"Got a new BWM"<<endl;
}
};
class Audi : public Car
{
public:
Audi(string name) :Car(name){}
void show(){
cout<<"Got a new Audi"<<endl;
}
};
enum CarType{
BMW , AUDI
};
//创建一个大工厂,为其他工厂提供同一的抽象方法
class Factory{
public:
virtual Car* createCar(string name) = 0;
};
class BWMFactory : public Factory{
public:
virtual Car* createCar(string name){
return new Bmw(name);
}
};
class AudiFactory : public Factory{
public:
virtual Car* createCar(string name){
return new Audi(name);
}
};
signed main(){
unique_ptr<Factory> BwmFactory(new BWMFactory()) ;
unique_ptr<Car> car1(BwmFactory->createCar("X3"));
unique_ptr<Factory> audiFactory(new AudiFactory()) ;
unique_ptr<Car> car2(audiFactory->createCar("R6"));
car1->show() , car2->show();
return 0;
}
抽象工厂
把有关联关系的,属于一个产品簇的所有产品常见的接口函数,放在一个抽象工厂里面
派生类(具体产品的工厂)应该负责创建产品簇里面的所有产品
#include<iostream>
#include<string>
#include<memory>
using namespace std;
//假设宝马公司还生产灯,那么应该把灯放在宝马公司的工厂内生产
//不用额外创建新的灯工厂(避免额外的派生类过多不好维护)
class Light{
public:
Light(string name):_name(name){}
void show() {cout<<"this is a light call :" << _name<<endl;}
private:
string _name;
};
class BwmLight : public Light{
public:
BwmLight(string name) :Light(name){};
};
class Car
{
public:
Car(string name):_name(name){}
virtual void show() = 0;
protected:
string _name;
};
class Bmw : public Car
{
public:
Bmw(string name) :Car(name){}
void show(){
cout<<"Got a new BWM"<<endl;
}
};
class Audi : public Car
{
public:
Audi(string name) :Car(name){}
void show(){
cout<<"Got a new Audi"<<endl;
}
};
enum CarType{
BMW , AUDI
};
//
class Factory{
public:
virtual Car* createCar(string name) = 0;
virtual Light* createLight(string name) = 0;
};
class BWMFactory : public Factory{
public:
virtual Car* createCar(string name){
return new Bmw(name);
}
virtual Light* createLight(string name){
return new BwmLight(name);
}
};
class AudiFactory : public Factory{
public:
virtual Car* createCar(string name){
return new Audi(name);
}
virtual Light* createLight(string name){};
};
signed main(){
unique_ptr<Factory> BwmFactory(new BWMFactory()) ;
unique_ptr<Car> car1(BwmFactory->createCar("X3"));
unique_ptr<Light> light1(BwmFactory->createLight("ll"));
unique_ptr<Factory> audiFactory(new AudiFactory()) ;
unique_ptr<Car> car2(audiFactory->createCar("R6"));
car1->show() , car2->show() , light1->show();
return 0;
}
适配器模式
适配器模式:让不兼容的接口一起工作
电脑 ->投影(VGA,HDMI,Type-C)等 ->投影仪
VGA接口的电脑 == VGA投影仪(就不需要接口转换)
#include<iostream>
#include<memory>
using namespace std;
//VGA接口类
class VGA
{
public:
virtual void play() = 0;
};
//HDMI接口类
class HDMI
{
public:
virtual void play() = 0;
};
//支持VGA接口的投影仪
class TV01 : public VGA
{
public:
virtual void play() {
cout<<"Play By VGA";
}
};
//支持HDMI接口的投影仪
class TV02 : public HDMI
{
public:
virtual void play() {
cout<<"Play By HDMI";
}
};
// 方法一:换电脑(即进行代码重构)
// 方法二: 买一个转换头,能够把VGA信号转换成HDMI信号(适配器方法)
class Computer1
{
public:
// 由于电脑只支持VGA接口,所以偶该方法的参数也只能支持VGA接口的指针/引用
void playVideo(VGA *pVGA){
pVGA ->play();
}
};
//由于电脑(VGA接口)与投影仪(HDMI接口)不兼容,所以需要添加适配器类
class VGAToHDMIAdapter: public VGA
{
public:
VGAToHDMIAdapter(HDMI *p) : pHdmi(p){}
void play(){
pHdmi->play();
}
private:
HDMI* pHdmi;
};
signed main(){
unique_ptr<Computer1> com(new Computer1);
com->playVideo(new VGAToHDMIAdapter(new TV02));
}
装饰器模式
Decorator 装饰器模式
属于一个结构性模式
与代理模式非常相似
通过子类实现的方式来完成功能增强的问题,为了增强现有类的功能,通过实现子类的方式