其他分享
首页 > 其他分享> > 常用设计模式总结

常用设计模式总结

作者:互联网

设计模式的相关知识,很多书籍和博客中都有详细总结,本文总结的目的:
1、将自己学习到的设计模式的知识按照自己的逻辑重新总结,方便查看和记忆。
2、方便让自己对设计模式中常用的知识有一个系统的认知。

设计模式

《⼤话设计模式》⼀书中提到 24 种设计模式,这 24 种设计模式没必要⾯⾯俱到,但⼀定要深⼊了解其中的⼏种,最好结合⾃⼰在实际开发过程中的例⼦进⾏深⼊的了解。

设计模式分类

设计模式分为三类:

几种常见的设计模式

单例模式

单例模式的适用场景

所以单例模式一般用在对实例数量有严格要求的地方,比如数据池,线程池,缓存,session回话等等。

构成的条件:

单例模式有两种:饿汉模式和懒汉模式

《C++ 单例模式》https://zhuanlan.zhihu.com/p/37469260

《析构函数声明为私有的作用》https://blog.csdn.net/jia_xiaoxin/article/details/3348045

饿汉模式

饿汉模式(线程安全):顾名思义,饿了就饥不择⻝了,所以在单例类定义的时候就进行实例化。

在最开始的时候静态对象就已经创建完成,设计方法是类中包含⼀个静态成员指针,该指针指向该类的⼀个对象,提供⼀个公有的静态成员方法,返回该对象指针,为了使得对象唯⼀,构造函数设为私有。由于在main函数之前初始化,所以没有线程安全的问题。

#include <iostream>
#include <algorithm>
using namespace std;
class SingleInstance {
public:
    // 用户通过接口获取实例:使用 static 类成员函数
	static SingleInstance* GetInstance() {
		return &ins;
	}	
private:
    static SingleInstance ins;  // 注意此处不是指针
private:
	//涉及到创建对象的函数都设置为private
    SingleInstance(){}
	SingleInstance() { std::cout<<"SingleInstance() 饿汉"<<std::endl; }
	SingleInstance(const SingleInstance& other) {};
	SingleInstance& operator=(const SingleInstance& other) {return *this; }
    ~SingleInstance(){};
};
SingleInstance SingleInstance::ins;  // 静态成员函数定义并初始化

int main() {
	//因为不能创建对象所以通过静态成员函数的⽅法返回静态成员变量
	SingleInstance* ins = SingleInstance::GetInstance();
	return 0; 
}
//输出 SingleInstance() 饿汉

懒汉模式

懒汉(线程安全需要加锁):顾名思义,不到万不得已就不会去实例化类,也就是在第⼀次⽤到的类实例的时候才会去实例化。尽可能的晚的创建这个对象的实例,即在单例类第⼀次被引⽤的时候就将自己初始化,C++ 很多地方都有类型的思想,比如写时拷贝,晚绑定等。

原始版

class SingleInstance
{
private:
	static SingleInstance* instance;  // 与饿汉模式相比,此处是指针
private:
	SingleInstance() {};
	~SingleInstance() {};
	SingleInstance(const SingleInstance&);
	SingleInstance& operator=(const SingleInstance&);
public:
	static SingleInstance* getInstance() 
        {
		if(instance == NULL) 
			instance = new SingleInstance();
		return instance;
	}
};

// init static member
SingleInstance* SingleInstance::instance = NULL;

这种原始的方法存在内存泄露的问题,有两种解决方法:

  1. 使用智能指针
  2. 使用静态的嵌套类对象

对于第二种解决方法,代码如下:

class SingleInstance
{
private:
	static SingleInstance* instance;
private:
	SingleInstance() { };
	~SingleInstance() { };
	SingleInstance(const SingleInstance&);
	SingleInstance& operator=(const SingleInstance&);
private:
	class Deletor {
	public:
		~Deletor() {
			if(SingleInstance::instance != NULL)
				delete SingleInstance::instance;
		}
	};
	static Deletor deletor;
public:
	static SingleInstance* getInstance() {
		if(instance == NULL) {
			instance = new SingleInstance();
		}
		return instance;
	}
};
// init static member
SingleInstance* SingleInstance::instance = NULL;

在程序运行结束时,系统会调用静态成员deletor的析构函数,该析构函数会删除单例的唯一实例。使用这种方法释放单例对象有以下特征:

这个代码在单线程环境下是正确无误的,但是当拿到多线程环境下时这份代码就会出现race condition, 要使其线程安全,能在多线程环境下实现单例模式,我们首先想到的是利用同步机制来正确的保护我们的shared data。

#include <pthread.h>
#include <iostream>
#include <algorithm>
using namespace std;
class SingleInstance {
public:
	static SingleInstance* GetInstance() {
		if (ins == nullptr) {
			pthread_mutex_lock(&mutex);
			if (ins == nullptr) {
				ins = new SingleInstance();
			}
			pthread_mutex_unlock(&mutex);
		}
		return ins;
	}
	~SingleInstance(){};
	//互斥锁
	static pthread_mutex_t mutex;
private:
	//涉及到创建对象的函数都设置为private
	SingleInstance() { std::cout<<"SingleInstance() 懒汉"<<std::endl; }
	SingleInstance(const SingleInstance& other) {};
	SingleInstance& operator=(const SingleInstance& other) { return *this; }
	//静态成员
	static SingleInstance* ins;
};

//懒汉式 静态变量需要定义
SingleInstance* SingleInstance::ins = nullptr;
pthread_mutex_t SingleInstance::mutex;

int main(){
	//因为不能创建对象所以通过静态成员函数的⽅法返回静态成员变量
	SingleInstance* ins = SingleInstance::GetInstance();
	delete ins;
	return 0; 
}
//输出 SingleInstance() 懒汉

工厂模式

⼀般情况下,工厂模式分为三种更加细分的类型:简单工厂、工厂⽅法和抽象工厂。

简单工厂模式

可以根据实际的参数不同返回不同的实例。同时在简单工厂模式中会定义⼀个类负责创建其他 类的实例,被创建的实例也通常具有共同的⽗类。简单工厂模式的实质是由⼀个工厂根据传⼊的参数,动态决定应该创建哪⼀个产品类(这些产品类继承⾃⼀个⽗类或接接口)的实例。

#include <iostream>
#include <pthread.h>
using namespace std;
//产品类(抽象类,不能实例化)
class Product{
public:
	Product(){};
	virtual void show()=0; //纯虚函数
};

class productA : public Product{
public:
	productA(){};
	void show(){ std::cout << "product A create!" << std::endl; };
	~productA(){};
};

class productB : public Product{
public:
	productB(){};
	void show(){ std::cout << "product B create!" << std::endl; };
	~productB(){};
};

class simpleFactory{ // ⼯⼚类
public:
	simpleFactory(){};
	Product* product(const string str){
		if (str == "productA")
			return new productA();
		if (str == "productB")
			return new productB();
		return NULL;
	};
};

int main(){
	simpleFactory obj; // 创建⼯⼚
	Product* pro; // 创建产品
	pro = obj.product("productA");
	pro->show(); // product A create!
	delete pro;
	pro = obj.product("productB");
	pro->show(); // product B create!
	delete pro;
	return 0; 
}

工厂模式⽬的就是代码解耦,如果我们不采⽤工厂模式,如果要创建产品 A、B,通常做法采⽤⽤ switch…case语句,那么想⼀想后期添加更多的产品进来,我们不是要添加更多的switch…case 吗?这样就很麻烦,⽽且也不符合设计模式中的开放封闭原则

抽象工厂模式

为了进⼀步解耦,在简单工厂的基础上发展出了抽象工厂模式,即连工厂都抽象出来,实现了 进⼀步代码解耦。

#include <iostream>
#include <pthread.h>
using namespace std;
//产品类(抽象类,不能实例化)
class Product{
public:
	Product(){}
	virtual void show()=0; //纯虚函数
};

class Factory{//抽象类
public:
	virtual Product* CreateProduct()=0;//纯虚函数
};

//产品A
class ProductA:public Product{
public:
	ProductA(){}
	void show(){ std::cout<<"product A create!"<<std::endl; };
};

//产品B
class ProductB:public Product{
public:
	ProductB(){}
	void show(){ std::cout<<"product B create!"<<std::endl; };
};

//⼯⼚类A,只⽣产A产品
class FactorA: public Factory{
public:
	Product* CreateProduct(){
		Product* product_ = nullptr;
		product_ = new ProductA();
		return product_;
	}
};

//⼯⼚类B,只⽣产B产品
class FactorB: public Factory{
public:
	Product* CreateProduct(){
		Product* product_ = nullptr;
		product_ = new ProductB();
		return product_;
	}
};

int main(){
	Product* product_ = nullptr;
	auto MyFactoryA = new FactorA();
	product_ = MyFactoryA->CreateProduct();// 调⽤产品A的⼯⼚来⽣产A产品
	product_->show();
	delete product_;
	auto MyFactoryB=new FactorB();
	product_ = MyFactoryB->CreateProduct();// 调⽤产品B的⼯⼚来⽣产B产品
	product_->show();
	delete product_;
	return 0; 
}
//输出
//product A create! product B create!

观察者模式

观察者模式定义⼀种⼀(被观察类)对多(观察类)的关系,让多个观察对象同时监听⼀个 被观察对象,被观察对象状态发⽣变化时,会通知所有的观察对象,使他们能够更新⾃⼰的状态。 观察者模式中存在两种⻆⾊:

应⽤场景:

#include <iostream>
#include <string>
#include <list>
using namespace std;
class Subject;

//观察者 基类 (内部实例化了被观察者的对象sub)
class Observer {
protected:
	string name;
	Subject *sub;
public:
	Observer(string name, Subject *sub) {
		this->name = name;
		this->sub = sub;
	}
	virtual void update() = 0;
};

class StockObserver : public Observer {
public:
	StockObserver(string name, Subject *sub) : Observer(name, sub){}
	void update();
};

class NBAObserver : public Observer {
public:
	NBAObserver(string name, Subject *sub) : Observer(name, sub){}
	void update();
};

//被观察者 基类 (内部存放了所有的观察者对象,以便状态发⽣变化时,给观察者发通知)
class Subject {
protected:
	std::list<Observer *> observers;
public:
	string action; //被观察者对象的状态
	virtual void attach(Observer *) = 0;
	virtual void detach(Observer *) = 0;
	virtual void notify() = 0;
};

class Secretary : public Subject {
	void attach(Observer *observer) {
		observers.push_back(observer);
	}
	void detach(Observer *observer) {
		list<Observer *>::iterator iter = observers.begin();
		while (iter != observers.end()) {
			if ((*iter) == observer) {
			observers.erase(iter);
			return;
			}
			++iter;
		}
	}
	void notify() {
		list<Observer *>::iterator iter = observers.begin();
		while (iter != observers.end()) {
			(*iter)->update();
			++iter;
		}
	}
};
void StockObserver::update() {
	cout << name << " 收到消息:" << sub->action << endl;
	if (sub->action == "⽼板来了!") {
		cout << "我⻢上关闭股票,装做很认真⼯作的样⼦!" << endl;
	}
}
void NBAObserver::update() {
	cout << name << " 收到消息:" << sub->action << endl;
	if (sub->action == "⽼板来了!") {
		cout << "我⻢上关闭 NBA,装做很认真⼯作的样⼦!" << endl;
	}
}
int main()
{
	Subject *BOSS = new Secretary();
	Observer *xa = new NBAObserver("xa", BOSS);
	Observer *xb = new NBAObserver("xb", BOSS);
	Observer *xc = new StockObserver("xc", BOSS);
	BOSS->attach(xz);
	BOSS->attach(xb);
	BOSS->attach(xc);
	BOSS->action = "去吃饭了!";
	BOSS->notify();
	cout << endl;
	BOSS->action = "⽼板来了!";
	BOSS->notify();
	return 0; 
}
//输出
//product A create! product B create!

装饰器模式

装饰器模式(Decorator Pattern)允许向⼀个现有的对象添加新的功能,同时⼜不改变其结构。
这种类型的设计模式属于结构型模式,它是作为现有的类的⼀个包装。
如下代码中没有改变 Car 类的内部结构,还为其增加了新的功能,这就是装饰器模式的作⽤。

#include <iostream>
#include <list>
#include <memory>
using namespace std;
//抽象构件类 Transform (变形⾦刚)
class Transform{
public:
	virtual void move() = 0;
};

//具体构件类Car
class Car : public Transform{
public:
	Car(){
		std::cout << "变形⾦刚是⼀辆⻋!" << endl;
	}
	void move(){
		std::cout << "在陆地上移动。" << endl;
	}
};

//抽象装饰类
class Changer : public Transform{
public:
	Changer(shared_ptr<Transform> transform){
		this->transform = transform;
	}
	void move(){
		transform->move();
	}
private:
	shared_ptr<Transform> transform;
};

//具体装饰类Robot
class Robot : public Changer{
public:
	Robot(shared_ptr<Transform> transform) : Changer(transform){
		std::cout << "变成机器⼈!" << std::endl;
	}
	void say(){
		std::cout << "说话!" << std::endl;
	}
};

//具体装饰类AirPlane
class Airplane : public Changer{
public:
	Airplane(shared_ptr<Transform> transform) : Changer(transform){
		std::cout << "变成⻜机!" << std::endl;
	}
	void say(){
		std::cout << "在天空⻜翔!" << std::endl;
	} 
};
int main(void){
	shared_ptr<Transform> camaro = make_shared<Car>();
	camaro->move();
	std::cout << "--------------" << endl;
	shared_ptr<Robot> bumblebee = make_shared<Robot>(camaro);
	bumblebee->move();
	bumblebee->say();
   	std::cout << "--------------" << endl;
	shared_ptr<Airplane> bumblebee1 = make_shared<Airplane>(camaro);
	bumblebee1->move();
	bumblebee1->say();
	return 0;
}
/*
输出
变形⾦刚是⼀辆⻋!
在陆地上移动。
--------------
变成机器⼈!
在陆地上移动。
说话!
--------------
变成⻜机!
在陆地上移动。
在天空⻜翔!
*/

装饰器模式的优点:

1、可以轻松对已存在的对象进行修改和包装,在被装饰者的前面或者后面添加自己的行为,而无需修改原对象。

2、可以动态、不限量地进行装饰,可以更灵活地扩展功能。

相对地,装饰器模式有很明显的缺点:

1、会加入大量的小类,即使只添加一个功能,也要额外创建一个类,使得程序更复杂。

2、增加代码复杂度,使用装饰器模式不但需要实例化组件,还要把组件包装到装饰者中。

标签:总结,常用,实例,观察者,模式,class,SingleInstance,设计模式,public
来源: https://blog.csdn.net/weixin_45004203/article/details/122804204