设计模式

单例模式

package com.seven.exercise.testEception;


/**
 * 单例模式,饿汉式
 * @author Seven
 *
 */
public class SingleDemoHunger {


    private SingleDemoHunger() {


    }


    private static SingleDemoHunger sdh = new SingleDemoHunger();


    public static SingleDemoHunger getInstance() {
        return sdh;
    }


}


package com.seven.exercise.testEception;


/**
 * 懒汉式
 * @author Seven
 *
 */
public class SingleDemo {
    
    /**
     * 私有化构造函数
     */
    private SingleDemo(){
        
    }
    
    private static SingleDemo singleDemo = null;
    
    /**
     * 提供获取实例的方法
     * @return
     */
    public static SingleDemo getInstance(){
        if(singleDemo==null){
            singleDemo = new SingleDemo();
        }
        return singleDemo;
    } 
}

饿汉式属于立即加载,所以不存在在多线程中出现错误的情况;

但是懒汉式的话就有可能出现问题了,如多一个线程执行到判断是否为空的语句

if(singleDemo==null)

的时候,当前线程被阻塞,而第二个线程进来了,这样的话第二个线程创建了新的对象,那么第一个线程被唤醒的时候又创建多一个对象,这样在内存中就存在了两个对象,明显和单例设计模式不符,那么我们应该怎么做呢?

很简单,用 synchronized关键字就可以轻松解决:

package com.seven.exercise.testEception;


/**
 * 懒汉式
 * @author Seven
 *
 */
public class SingleDemo {
    
    /**
     * 私有化构造函数
     */
    private SingleDemo(){
        
    }
    
    private static SingleDemo singleDemo = null;
    
    /**
     * 提供获取实例的方法,用synchronized来解决多线程的问题.C++ 使用 lock() 和unlock()来实现
     * @return
     */
    public static SingleDemo getInstance(){
        synchronized (SingleDemo.class) {
            if(singleDemo==null){
                singleDemo = new SingleDemo();
            }
        }
        return singleDemo;
    }
    
    
}


这样就减少了创建多个实例的可能,但是还是存在创建多个实例的可能性,而且同步锁肯定要消耗资源,这样的话就会降低效率,那么有什么办法可以提高效率呢?答案是有的,那就是通过二次判断,这样的话就不用每次都执行同步代码块,这样的话,只需第一次执行的时候比较占资源,以后的话就和之前的一样了:

package com.seven.exercise.testEception;


/**
 * 懒汉式
 * @author Seven
 *
 */
public class SingleDemo {
    
    /**
     * 私有化构造函数
     */
    private SingleDemo(){
        
    }
    
    private static SingleDemo singleDemo = null;
    
    /**
     * 提供获取实例的方法,用synchronized来解决多线程的问题.
     * @return
     */
    public static SingleDemo getInstance(){
        //二次判断提高效率
        if(singleDemo==null){
            synchronized (SingleDemo.class) {
                if(singleDemo==null){
                    singleDemo = new SingleDemo();
                }
            }
        }
        return singleDemo;
    }
    
    
}


设计模式中的单例模式的代码为什么析构函数会多次被调用,而构造函数只调用一次


********************************************************************
 created: 2006/07/20
 filename:  Singleton.h
 author:  李创
                http://www.cppblog.com/converse/

 purpose: Singleton模式的演示代码
*********************************************************************/

#ifndef SINGLETON_H
#define SINGLETON_H

class Singleton
{
public:
 Singleton();
 ~Singleton();

 // 静态成员函数,提供全局访问的接口
 static Singleton* GetInstancePtr();
 static Singleton  GetInstance();

 void Test();

private:
 // 静态成员变量,提供全局惟一的一个实例
 static Singleton* m_pStatic;
};

#endif

 

/********************************************************************
 created: 2006/07/20
 filename:  Singleton.cpp
 author:  李创
                http://www.cppblog.com/converse/

 purpose: Singleton模式的演示代码
*********************************************************************/

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

// 类的静态成员变量要在类体外进行定义
Singleton* Singleton::m_pStatic = NULL;

Singleton::Singleton()
{
     std::cout << "构造函数被调用/n";
}

Singleton::~Singleton()
{
     std::cout << "析构函数被调用/n";
}

Singleton* Singleton::GetInstancePtr()
{
 if (NULL == m_pStatic)
 {
  m_pStatic = new Singleton();
 }

 return m_pStatic;
}

Singleton Singleton::GetInstance()
{
 return *GetInstancePtr();
}

void Singleton::Test()
{
 std::cout << "Test函数被调用!/n";
}

 

/********************************************************************
 created: 2006/07/20
 filename:  Main.cpp
 author:  李创
                http://www.cppblog.com/converse/

 purpose: Singleton模式的测试代码
*********************************************************************/

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

 

//析构函数只被调用一次的情形:

int main()
{
 // 不用初始化类对象就可以访问了
 for( int i =0; i < 10; i++)

{

     Singleton::GetInstancePtr()->Test();//程序执行完这一句之后析构函数被调用一次,如果是第一次,构造函数被调用

   //并且构造函数只被调用一次

 

}

 return 0;
}

 

 

程序运行结果:

构造函数被调用
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!

 

析构函数多次被调用的情况:

void Test();

int g_iTest = 0;

int main()
{

 for( int i = 0; i < 5; i++ )//析构函数5次被调用
 {
  Test();
 }

 system("pause");

 return 0;
}

void Test()
{
 g_iTest++;
 printf( "第 %d 次调用成员函数", g_iTest );
 Singleton::GetInstance().Test();
 
 printf( "/n/n" );
}

第 1 次调用成员函数(构造函数被调用)Test!
(析构函数被调用)

第 2 次调用成员函数Test!
(析构函数被调用)

第 3 次调用成员函数Test!
(析构函数被调用)

第 4 次调用成员函数Test!
(析构函数被调用)

第 5 次调用成员函数Test!
(析构函数被调用)

请按任意键继续. . .


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值