💻文章目录
- 📄前言
- 🌻特殊类的设计
- 无法被继承的类
- 只能在堆开辟空间的类
- 无法被拷贝的类
- 只能在栈开辟空间的类
- 🌺单例模式
- 饿汉模式
- 懒汉模式
- 📓总结
📄前言
你可听说过只能在堆上创建的类、无法被拷贝的类、甚至是不能继承的类,如果你从未听闻过这样的奇妙的类设计,不妨点进本篇文章,来进入学习设计模式的第一步。
🌻特殊类的设计
当你看到这些要实现的特殊类,可能会感到困惑,为什么需要做出这种看似没有任何意义的类,此时不妨自己动手来实现一下它们,这些看似无用的设计,其实正是通向设计模式的第一步。
无法被继承的类
class NonInherit final //c++11中,直接使用final即可
{NonInherit() {}
};class NonInherit //c++98
{
private:NonInherit(){} //私有构造函数即可阻止类被继承
}
只能在堆开辟空间的类
限制类的实例只能在堆上创建,可以通过构造函数私有化,然后通过一个静态的函数来创建类。
class HeapOnly
{
public:static HeapOnly* creat() //静态函数来返回地址{return new HeapOnly;}
private:HeapOnly() {}; //设为私有HeapOnly(const HeapOnly&) = delete;
};
无法被拷贝的类
防止类的对象被拷贝,可以通过删除拷贝构造函数和赋值运算符来实现。
class Noncopy
{
public:Noncopy() {}Noncopy &operator=(const Noncopy &) = delete; //也可设为私有Noncopy(const Noncopy &) = delete;
};
只能在栈开辟空间的类
只要在类内把拷贝函数和赋值函数给设为私有或者使用delete(c++11)即可做出在栈开辟空间的类。
class StackOnly
{
public:void* operator new(size_t) = delete;void operator delete(void*) = delete;static StackOnly create(){return StackOnly();}
private:StackOnly() {}
};
🌺单例模式
单例模式是一种常用的设计模式,其核心是确保程序中只能一个类只能拥有一个实例,从而实现资源重复利用性,减少性能的损耗。
有了上方特殊类的创建思路,就能更理解饿汉模式与懒汉模式
饿汉模式
饿汉模式,在程序加载类的时候就马上加载实例,这样一来就保证了实例的唯一性。
优点:
- 没有线程安全问题,因为在线程开始就被创建。
- 实现简单。
缺点:
- 可能会造成资源浪费,特别是在还没有用到实例的时候。
- 无法控制类的加载顺序,因为在程序加载时就运行,所以会拉慢程序加载速度。
class SingletonEager // 饿汉模式,正如其名一拿到资源就吃掉
{ // 优点:简单、
public: // 缺点:可能会造成资源的浪费,没有使用的情况static SingletonEager &getInstance(){return _instance;}private:SingletonEager(){};SingletonEager(const SingletonEager &) = delete;SingletonEager &operator=(const SingletonEager &) = delete;static SingletonEager &_instance;
};
懒汉模式
懒汉模式指的是在需要用到实例的时候再创建,以此来保证资源不被浪费。
优点:
- 减缓内存压力,如果没有用到实例则内存不会被分配。
- 加载速度较快。只有在使用时才被创建。
缺点:
- 线程安全问题:如果有多个线程同时访问类,需要自己保证资源不会被同时访问,出现二义性问题。
- 相比于饿汉模式,实现比较复杂。
class SingletonLazy // 懒汉模式,在需要使用到实例的时候再创建实例,杜绝了资源浪费。
{ // 优点:
public: // 缺点:SingletonLazy(const SingletonLazy &) = delete;SingletonLazy &operator=(const SingletonLazy &) = delete;static SingletonLazy *getInstance(){std::lock_guard(_mtx); // 多线程情况下,防止二义性情况出现。if (_instance == nullptr){_instance = new SingletonLazy;}} // lock_guard 会自动释放 RAIIprivate:SingletonLazy(){};static SingletonLazy *_instance;static std::mutex _mtx;
};
📓总结
设计模式是前人总结出来的开发模板,每一个程序员都应该对它们有所了解,设计模式大致分为三类:创建型、结构型、行为型,本篇介绍了创建型的单例模式,但细算设计模式,一共有23种之多,这些设计模式让我们日后再谈。
单例模式类型 | 饿汉模式 | 懒汉模式 |
---|---|---|
优点: | 在程序启动时就完成了单例的初始化,保证了线程安全。实现简单。 | 单例实例在需要时才被创建,可以节省资源。对于资源消耗较大的单例,或者在初始化过程中需要依赖参数的情况下非常有用。 |
缺点: | 如果程序启动后,单例未被使用,则会造成资源的浪费。初始化单例的过程可能会增加应用程序启动时间。 | 需要在多线程环境下确保线程安全,实现相对复杂,可能会影响性能 |
📜博客主页:主页
📫我的专栏:C++
📱我的github:github