• 单例设计模式的一点总结


    单例模式:

    1、什么叫做单例模式?

    单例模式保证一个类仅有一个实例,并且提供一个访问他的全局访问点。

    2、单例模式要解决什么问题?

    在游戏编程中,我们会在客户端给玩家提供一些面板,展示玩家属性,玩家背包,玩家技能等等。如果我们每一次都是去实例化一个对象,这个是否当玩家不断打开背包的时候,就可能出现无数个背包面板。

    3、单例模式怎么解决问题?

    那么怎么能只创建一个背包面板呢,这个时候我们就需要只确保一个对象被实例化,我们来想想怎么来确保一个面板被实例化。首先我们可以设定这个

    KUiErrorMessageBox& KUiErrorMessageBox::GetSingleton()

    {

    static KUiErrorMessageBox singleton;

    return singleton;

    }

    调用

    KUiErrorMessageBox::GetSingleton().AddMessage( AnsiToUtf8( msg ) );

    4、单例模式的好处

    保证唯一的实例

    可以严格地控制客户怎样访问它以及何时访问它。唯一实例的受控访问

    5、多线程下的单例模式

    此部分引用:http://blog.csdn.net/joanlynnlove/article/details/7462254

    多线程的时候可能会出现每个线程都来初始化一个实例,这个时候我们应该如何来处理呢。我们要使用多线成中的lock来加锁,

    项目中需要在多线程环境下,输出日志到标准输出,以下是实现过程。

    首先,我们需要一个锁类,能够自动初始化,并且降低耦合。print?

    其次,声明日志类,重点是将构造函数私有化,将函数成员和数据成员声明为静态,添加实例指针和全局访问点。

    /*
     * locker.h
     *
     *  Created on: Apr 14, 2012
     *      Author: joan
     */
    
    #ifndef LOCKER_H_
    #define LOCKER_H_
    
    #include "../OPTION.h"
    
    class locker
    {
    public:
    	inline locker(){		pthread_mutex_init(&mutex,NULL);}
    	inline ~locker(){		pthread_mutex_destroy(&mutex);}
    	inline void lock(){		pthread_mutex_lock(&mutex);}
    	inline void unlock(){	pthread_mutex_unlock(&mutex);}
    private:
    	pthread_mutex_t mutex;
    };
    
    #endif /* LOCKER_H_ */


     

    其次,声明日志类,重点是将构造函数私有化,将函数成员和数据成员声明为静态,添加实例指针和全局访问点。

    /*
     * log.h
     *
     *  Created on: Apr 8, 2012
     *      Author: joan
     */
    
    #ifndef LOG_H_
    #define LOG_H_
    
    #include "../OPTION.h"
    #include "locker.h"
    
    /*
     * this class is responsible for the running log of tinyJSE
     * there should only exist one instance of tinyLog,
     * so we use singleton to implement tinyLog
     */
    class tinyLog
    {
    public:
    	static tinyLog *GetInstance();
    	static void WriteLog(const char *FORMAT,...);
    private:
    	tinyLog();
    	~tinyLog();
    private:
            static tinyLog *log;
    static locker llock;
    };
    #endif /* LOG_H_ */


    然后是日志类的实现,注意全局访问点中使用double check提高性能。

    /*
     * log.cpp
     *
     *  Created on: Apr 8, 2012
     *      Author: joan
     */
    
    #include "../OPTION.h"
    #include "log.h"
    
    tinyLog * tinyLog::log = NULL;
    locker tinyLog::llock;
    
    tinyLog::tinyLog()
    {
    }
    
    tinyLog::~tinyLog()
    {
    }
    
    /*
     * get the pointer to the only instance of tinyLog
     * use double check to assure only one instance is created
     */
    tinyLog *tinyLog::GetInstance()
    {
    	if(NULL == log)
    	{//double check
    		llock.lock();
    		if(NULL == log)
    		{
    			log = new tinyLog();
    		}
    		llock.unlock();
    	}
    	return log;
    }
    
    /*
     * Unified handling of the log of tinyJSE
     */
    void tinyLog::WriteLog(const char *FORMAT,...)
    {
    	va_list args;
    
    	va_start(args, FORMAT);
    
    	llock.lock();
    
    	vfprintf(stdout,FORMAT,args);
    
    	llock.unlock();
    
    	va_end(args);
    
    }


    使用该单例:

    #define PRINT(FORMAT,args...)	tinyLog::GetInstance()->WriteLog(FORMAT,##args)


     

    6、双重锁定

    这里面要特别注意,这里做了双重锁定,为什么要这么做呢,主要在于这样做不用让线程每次都加锁,而只是在实例未被创建的时候再加锁处理,同事也能保证多线程的安全。

    当instancenull的时候并且同时有两个线程调用GetInstance()方法时,它们都可以通过第一层的null判断,然后由于lock机制两个线程则只有一个进入,另一个在外面排队等候,必须等一个进去出来后另一个才能进去。如果没有第二次的null判断另一个线程就可以创建新的实例了,那就不是单例了哦

  • 相关阅读:
    使用CSS3美化复选框checkbox
    MYSQL select时锁定记录问题
    SQL Server中的锁
    T-SQL查询进阶—理解SQL Server中的锁
    SQL:查找被锁的表,以及锁表的SQL语句(重点推荐)
    Mac 常用的手势
    Mac 常用的快捷键
    Mac上的学习神器:Marginnote
    Mac 常用命令介绍
    Mac 上的传奇效率神器 Alfred 3
  • 原文地址:https://www.cnblogs.com/riasky/p/3468940.html
Copyright © 2020-2023  润新知