C++编程(二)—— 设计模式

文章目录

  • 单例模式
    • 饿汉式单例模式
    • 懒汉式单例模式
    • 懒汉式单例模式2
  • 工厂模式(创建型模式)
    • 简单工厂
    • 工厂方法
    • 抽象工厂
    • 总结


单例模式

一个类不管创建多少次多线,永远只能得到该类型一个对象的实例。

A* p1 = new A();
A *p2 = new A();
A *p3 = new A();

常用的为日志模块,数据库模块。

方法:
1、构造函数私有化,拷贝构造,赋值重载去除;
2、定义一个唯一的类的实例对象;
3、获取类唯一实例对象的静态方法(因为没有对象,必须通过静态方法获取)

class Singleton
{
public:
	static Singleton* getInstance()
	{
		return &instance;
	}

private:
	static Singleton instance;
	Singleton(){};
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
}
Singleton Singleton::instance;

int main()
{
	Singleton* p1 = Singleton::getInstance();
	Singleton* p2 = Singleton::getInstance();
	Singleton* p3 = Singleton::getInstance();
	// p1 p2 p3地址相同
	Singleton t = *p1;  // 错误
	return 0;
}

饿汉式单例模式

如上。
因为在程序启动时,实例对象就已经初始化好了,所以饿汉式一定线程安全
但是对象类的构造函数可能很复杂,于是有懒汉单例模式。

懒汉式单例模式

class Singleton
{
public:
	static Singleton* getInstance()
	{
		if(instance == nullptr)  
		{
			instance = new Singleton();
		}
		return &instance;
	}

private:
	static Singleton *instance;
	Singleton(){};
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
}
Singleton Singleton::instance = nullptr;

int main()
{
	Singleton* p1 = Singleton::getInstance();
	Singleton* p2 = Singleton::getInstance();
	Singleton* p3 = Singleton::getInstance();
	// p1 p2 p3地址相同
	Singleton t = *p1;  // 错误
	return 0;
}

懒汉式单例模式不是线程安全,getInstance方法不是可重入函数。

解决方案:锁+双重判断,实现线程间的互斥。

static Singleton* getInstance()
{
	if(instance == nullptr)
	{
		lock_guard<std::mutex> guard(mtx);
		if(instance == nullptr)
			instance = new Singleton();
	}
	return &instance;
}

static Singleton *volatile instance;

类外初始化:
Singleton *volatile Singleton::instance = nullptr;

使用volatile有一个线程给instance new时,其他线程立马就能知晓。

懒汉式单例模式2

保障线程安全。

class Singleton
{
public:
	static Singleton* getInstance()
	{
		static Singleton instance;  // 互斥动作,线程安全
		return &instance;
	}

private:
	Singleton()
	{ 
		很多初始化的代码
	}
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
}

int main()
{
	
	return 0;
}

在getInstance方法中,静态对象的初始化本身就是一个线程互斥的动作,所以线程安全。

工厂模式(创建型模式)

作用:主要是封装对象的创建。

简单工厂

不属于正规的设计模式

#include
using namespace std;

class product {
public:
    virtual void show() = 0;
};

class productA : public product{
public:
    void show() {
        cout << "productA" << endl;
    }
};

class productB : public product{
public:
    void show() {
        cout << "productB" << endl;
    }
};

enum Type {
    type1,
    type2
};
class Factory {
public:
    product *Create(enum Type type) {
        switch(type) {
            case type1:
                return new productA();
            case type2:
                return new productB();
            default:
                break;
        }
    }
};

int main() {
    Factory factory;
    factory.Create(type1)->show();
    factory.Create(type2)->show();
    
    return 0;
}

不满足开闭原则,而且一个工厂干的事情太多。

工厂方法

汽车类
C++编程(二)—— 设计模式_第1张图片
C++编程(二)—— 设计模式_第2张图片

工厂类:
C++编程(二)—— 设计模式_第3张图片C++编程(二)—— 设计模式_第4张图片
调用:
C++编程(二)—— 设计模式_第5张图片

抽象工厂

1是实际上很多产品是有关联的,不应该放在不同的工厂创建,2是工厂的子类型太多,写不完。
需要将工厂方法转换为抽象工厂。

C++编程(二)—— 设计模式_第6张图片

总结

C++编程(二)—— 设计模式_第7张图片

你可能感兴趣的:(c++,设计模式,单例模式)