单例模式

C++单例模式

单例饿汉式

  • 加载类的时候初始化(不使用也会构造类,空间换时间)
#include <stdio.h>
#include <string>

class DriverManger
{
private:
  long m_nDate;
  int m_nDriverNum;
  std::string m_strDriverInfo;

private:
  // 私有构造函数,禁止new方式实例化
  DriverManger(){printf("new DriverManger.. 
");}

  // 私有析构,实例的生命周期是程序开始到结束,无需手动释放
  ~DriverManger(){printf("delete DriverManger.. 
");}

  // 禁止拷贝构造和赋值操作符
  DriverManger(DriverManger&)/*=delete*/;
  const DriverManger& operator=(const DriverManger&)/*=delete*/;

  static DriverManger instance;

public:
  static DriverManger& GetInstance(void)
  {
    return instance;
  }
};

//下面这个静态成员变量在类加载的时候就已经初始化好了
DriverManger DriverManger::instance;

int main(void)
{
  printf("begin main.. 
");
  DriverManger& driver1 = DriverManger::GetInstance();
  DriverManger& driver2 = DriverManger::GetInstance();

  printf("%p && %p",&driver1, &driver2);

  return 0;
}

单例懒汉式

  • 使用到时(调用getInstance方法)才构造类实例
  • 多线程造成的实例不唯一
#include <stdio.h>
#include <string>

class DriverManger
{
private:
  long m_nDate;
  int m_nDriverNum;
  std::string m_strDriverInfo;
  static DriverManger* theDriver;

private:
  // 私有构造函数,禁止new方式实例化
  DriverManger(){}

  // 禁止拷贝构造和赋值操作符
  DriverManger(DriverManger&)/*=delete*/;
  const DriverManger& operator=(const DriverManger&)/*=delete*/;

public:
  static DriverManger* GetInstance(void)
  {
    if (nullptr == theDriver)
    {
      theDriver = new DriverManger();
    }

    return theDriver;
  }

  ~DriverManger()
  {
    if (nullptr != theDriver)
    {
      delete theDriver;
    }
  }
};

DriverManger* DriverManger::theDriver = nullptr;

int main(void)
{
  DriverManger* pDriver = DriverManger::GetInstance();
  DriverManger* pDriver2 = DriverManger::GetInstance();
  printf("%p && %p 
", pDriver, pDriver2);

  getchar();

  return 0;
}

局部静态变量的单例懒汉式

  • 使用局部静态变量的特性保证了线程安全
#include <stdio.h>
#include <string>

class DriverManger
{
private:
  long m_nDate;
  int m_nDriverNum;
  std::string m_strDriverInfo;

private:
  // 私有构造函数,禁止new方式实例化
  DriverManger(){}

  // 禁止拷贝构造和赋值操作符
  DriverManger(DriverManger&)/*=delete*/;
  const DriverManger& operator=(const DriverManger&)/*=delete*/;

public:
  static DriverManger& GetInstance(void)
  {
    // 静态局部变量保证每次获取到唯一实例
    static DriverManger driver;
    return driver;
  }

  ~DriverManger(){}
};

int main(void)
{
  DriverManger& driver1 = DriverManger::GetInstance();
  DriverManger& driver2 = DriverManger::GetInstance();

  return 0;
}

JAVA单例模式

单例饿汉式

缺点是加载类就分配空间,浪费资源

  • 构造器私有
  • 提供外界可访问方法
public class Student {
	// 构造私有,外界不能直接创建
	private Student() {
	}

	// 类本身创建一个对象
	//private外界不能干预对象的赋值
	//static静态方法调用静态成员
	private static Student s = new Student();

	// 提供外界访问该对象的方法
	//static静态外界可以直接通过类名访问
	public static Student getStudent() {
		return s;
	}
	
	public void show(){
		System.out.println("hello");
	}

}

单例懒汉式(方法锁保证线程安全)

  • 效率低
public class Teacher {
	private Teacher(){	
	}
	
	private static Teacher t = null;
	
	//同步方法保证线程安全,因为有可能多个线程同时进入判断语句中
	public synchronized static Teacher getTeacher(){
		if(t==null){
			t = new Teacher();
		}
		return t;
	}
}

双重检测的懒汉式

/**
 * 线程安全的单例懒汉式
 */
public class ConcurrentSingle {
    private ConcurrentSingle(){

    }

    // volatile防止 new 时的指令重排
    private volatile static ConcurrentSingle theApp;

    // 双重检测锁
    public static ConcurrentSingle getTheApp() {
        if (theApp == null) {
            synchronized (ConcurrentSingle.class) {
                if (theApp == null) {
                    theApp = new ConcurrentSingle(); // 可能指令重排
                }
            }
        }
        return theApp;
    }
}

静态内部类单例模式

public class InnerSingle {
    private InnerSingle() {

    }

    public InnerSingle getInstance() {
        return Inner.HOLDER;
    }

    // 静态内部类
    private static class Inner{
        // 外部类的实例化对象
        private static final InnerSingle HOLDER = new InnerSingle();
    }
}

枚举实现单例

  • 线程安全
  • 可防止反射破坏
public enum EnumSingle {
    INSTANCE;
    private Resource resource;

    EnumSingle() {
        resource = new Resource();
    }

    public Resource getResource() {
        return resource;
    }
}

class Resource{

}

jdk中使用的单列模式

    Runtime r = Runtime.getRuntime();

源码

public class Runtime {
    private static Runtime currentRuntime = new Runtime();
    public static Runtime getRuntime() {
        return currentRuntime;
    }
...
原文地址:https://www.cnblogs.com/xiongyungang/p/13098582.html