设计模式的简单理解——单例模式

简单理解

单例模式是指进程生命期内,某个类型只实例化一个对象。这是一种通过语言特性实现的编程约束。如果没有约束,那么多人协同编码时,就会出现非预期的情况。

下面以内存池做例子,假设其类型名为MemoryPool。内存池的本意是统一管理全局内存,优化内存分配,提升性能,记录内存分配信息方便追溯问题,需要全局只有一个实例对象。

第一阶段:没有任何约束

因为没有任何约束,大家会各自实例化MemoryPool对象来使用。最终一片混乱,根本达不到最初使用内存池的目的。

第二阶段:编程语言外的约束

MemoryPool处添加注释,告诉大家只能使用一个MemoryPool的全局变量。刚开始还挺好,但总会有一些人不知道为什么就自己实例化MemoryPool对象来使用。因为破窗效应,最终越来越乱,出现第一阶段的情况。

第三阶段:编程语言的约束

MemoryPool的构造函数、拷贝构造函数、赋值构造函数都设为私有,只允许使用者通过一个接口来获取MemoryPool对象。当有人想自己实例化MemoryPool对象来使用时,编译就会报错。接口内只返回固定的一个已实例化的对象,完美!

实现

单例一般有两种方式

  • 程序初始化阶段时构造单例对象:进入main()之前构造,没有多线程问题,但不论是否使用都占用了资源
  • 使用时才构造单例对象:使用时才占用资源,但需要注意多线程竞争问题

以下是C++实现的单例代码
Singletion.h

#ifndef __SINGLETON_H__
#define __SINGLETON_H__

#include <mutex>

/**
 * @brief 单例模板
 * @detail 使用单例模式的类型需要将该模板设为友元类
 */
template<typename T>
class Singleton
{
public:
    static T* instance()
    {
        std::call_once( m_once, [](){ m_instance = new T; } );
        return m_instance;
    }

    static void destroy()
    {
        if( NULL != m_instance ){
            delete m_instance;
            m_instance = NULL;
        }
        return;
    }
private:
    static T* m_instance;
    static std::once_flag m_once;
};
template<typename T>
T* Singleton<T>::m_instance = NULL;

template<typename T>
std::once_flag Singleton<T>::m_once;

#endif

std::call_once()在Linux平台调用的是pthread_once()。flag有三个状态NEVER(0)、IN_PROGRESS(1)、DONE(2),其中使用了两个带LOCK前缀的指令:cmpxchg和incl。lock cmpxchg 将flag从0变为1,lock incl将flag从1变为2。lock锁定特定内存地址,避免其他CPU读取或者修改这个内存地址的值。

Adder.h

#ifndef __ADDER_H__
#define __ADDER_H__

#include "Singleton.h"
#include <atomic>

/**
 * @brief 累加器
 * @detail 使用单例模式,全局累加器
 */
class Adder
{
    friend class Singleton<Adder>;
public:
    Adder& operator<<(int32_t n)
    {
        m_num += n;
        return *this;
    }

    int32_t value()
    {
        return m_num;
    }
private:
    Adder()
    {
    }
    Adder(Adder&);
    Adder& operator=(Adder&);

private:
     std::atomic<int32_t> m_num;
};

#endif

main.cpp

#include "Adder.h"

#include <thread>
#include <vector>
#include <iostream>
void worker()
{
    int i = 1000000;
    while( i-- ){
        *(Singleton<Adder>::instance()) << 1;
    }
    return;
}
int main()
{
    std::vector<std::thread> threads;
    for( int i = 0; i < 10; ++i ){
        std::thread t( worker );
        threads.push_back( std::move( t ) );
    }

    for( int i = 0; i < 10; ++i ){
        threads[i].join();
    }
    // 输出等于1000万
    std::cout << Singleton<Adder>::instance()->value() << std::endl;
    return 0;
}

原文地址:https://www.cnblogs.com/yizui/p/10630820.html

时间: 2024-07-31 06:47:22

设计模式的简单理解——单例模式的相关文章

大话设计模式总结(28种设计模式定义+简单理解)

大话设计模式这本书写的非常有创意,非常适合我这种新手.用了大约两个星期的时间看完了这本书,代码全部都敲了一遍,虽然没有一点基础,但是还是领略到了面向对象的威力.看完之后再也不想使用面向过程的语言了,比如VB,想当初我也是VB狂热者,但是现在我几乎不想再使用了.现在只想着写点什么用上它几种设计模式. 可能是第一次接触这些东西,有些感觉看懂了,但是很难应用到实际编程中:有些感觉没看懂,但是还能说出那么点东西来.听七期学长说他们当初看了两遍,要求能背着写出代码,不知道这次我们八期要求怎么这么低,我只看

JavaScript设计模式的简单理解

设计模式可以理解为一系列的代码框架,我觉得主要涉及封装的概念.把实现某一功能的代码段封装在函数中,可以方便调用,同时利于代码的复用,提高了代码的可维护性.下面简单介绍一下几种设计模式的个人感受. 1.单例模式 类似于一个类只有一个对象实例. 假设一个物品只能归属于一个人所有.. 2.构造函数模式 类似于c中的构造函数,可以创建特定类型的对象,然后对象里可以声明不同的变量及成员函数,还可以有不同的参数.就像我想做个凳子,我可以做成普通的凳子,有长宽高之类的属性及可以做的功能函数,此外我也可以做成高

24种设计模式的简单理解

1.简单工厂模式 2.工厂方法模式 3.抽象工厂模式 4.建造者模式 5.原型模式 6.单例模式 7.适配器模式 8.桥接模式 9.组合模式 10.装饰模式 11.外观模式 12.享元模式 13.代理模式 14.职责链模式 15.命令模式 16.解释器模式 17.迭代器模式 18.中介者模式 19.备忘录模式 20.观察者模式 21.状态模式 22.策略模式 23.模板方法模式 24.访问者模式

装饰设计模式的简单理解

//装饰设计模式.//不修改原对象,对原有对象的功能进行增强.class Person{    void chifan()    {        System.out.println("吃饭");    }} class NewPerson{    private Person p;    NewPerson(Person p)    {        this.p = p;    }    public void newChifan()    {        System.out

设计模式-装饰模式简单理解

装饰模式是一种比较简单的模式,为什么要用它呢?怎么用呢? 前期需求:实现三个了A B C,定义相同的调用方法,客户可以有选择的调用任意一个. 我知道对接口编程,于是我定义了一个接口 interface O{ public void do(): } 然后我根据需求定义三个O的实现:A,B,C. 接下来的剧情: 1. 新需求来了:客户要在O的实现对象上增加功能F1或F2或F3. 怎么做?现在只有A B C三个,我用if else加上F1 F2 F3的支持: if(1) do F1 else if (

设计模式之简单理解装饰器模式与运用

1.什么是装饰器模式 ? 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. ? 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 2.装饰器模式的重要组成部分 ①装饰器模式特点: (1) 装饰对象和真实对象有相同的接口.这样客户端对象就能以和真实对象相同的方式和装饰对象交互. (2) 装饰对象包含一个真实对象的引用(reference

初识设计模式之--简单工厂

作为一个刚刚入门的菜鸟.虽只学到了些许编程语言的皮毛(或者连皮毛都算不上),但是随着时间和学习的深入,"设计模式"这一专业术语便慢慢浮现在眼前. 到底何为设计模式呢?它的出现将会给我们带来哪些帮助?......等等一系列问题便会出现在我们脑海中.俗话说:问题才是探究知识的钥匙.就让我们带着 自己的疑问一同来学习设计模式. 首先,我们先来认识一下什么是设计模式,以及运用设计模式的优点. 设计模式的简单理解:模式是在某一背景下某个问题的一种解决方案.1.复用解决方案——通过复用已经公认的设

设计模式之简单工厂和单例模式

近段时间发现自己越来越懒了,老师早就讲过的东西,一直没有总结!百度了一下,给的答案是设计模式总共23种.简单工厂属于其中一种,而单例模式并不是其中一种.今天总结下使用这两种模式写的项目. 设计模式:设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一

单例模式简单理解

单例模式 一般来说,一个类可以创建多个不同的对象,但是对于单例模式而言.这个单例类虽然也能创建"多个"对象,但是本质上来讲,这个对象其实就是一个. 单例模式的特点是:这个类只有一个对象,且这个对象是自己创建的,这个系统都要使用这个唯一的对象. 比如说,系统中的回收站,不管是哪个应用使用,都是一个回收站. 代码具体如下: public class MyDanLi { //1.私有化构造函数,在外面不能New来创建 private MyDanLi() { } //2.创建私有的静态的类的单