单例模式

Posted wq-9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。

单例模式官方定义

确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一的实例。

单例模式的实现机制

实现单例模式的思路是,为了防止客户程序利用构造方法创建多个对象,将构造方法声明为private类型。其原因是,如果构造方法为public类型,则客户程序永远可以通过使用改构造方法创建不同的对象。但这样做的问题是,如果一个类的构造方法是private的,则其他类无法使用该构造方法来创建对象,从而该类就成为不可用的了。为了解决此问题,该类必须提供一个实例方法,通常声明为getinstance方法。该方法返回一个实例。该方法为静态的,否则客户程序无法调用。

Volatile变量

程序设计中,尤其是在C语言C++C#Java语言中,使用volatile关键字声明的变量对象通常具有与优化、多线程相关的特殊属性。通常,volatile关键字用来阻止(伪)编译器认为的无法“被代码本身”改变的代码(变量/对象)进行优化。如在C语言中,volatile关键字可以用来提醒编译器它后面所定义的变量随时有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

在C环境中,volatile关键字的真实定义和适用范围经常被误解。虽然C++、C#和Java都保留了C中的volatile关键字,但在这些编程语言中volatile的用法和语义却大相径庭。

 

在C,以及C++中,volatile关键字的作用[1]

  • 允许访问内存映射设备
  • 允许在setjmplongjmp之间使用变量
  • 允许在信号处理函数中使用sig_atomic_t变量

根据相关的标准(C,C++,POSIX,WIN32)和目前绝大多数实现,对volatile变量的操作并不是原子的,也不能用来为线程建立严格的happens-before关系。volatile关键字就像便携式线程构建一样基本没什么用处[2][3][4][5][6]

Visual C++ 2005 保证volatile变量是一种内存屏障,阻止编译器和CPU重新安排读入和写出语义。[7] 在先前版本的Visual C++则没有此类保证。在其他方面将指针定义为volatile可能会影响程序的性能。例如,如果指针定义对代码的其他地方可见,强制编译器将指针视为屏障,就会降低程序的性能,这是完全不必要的。

对用户定义的非基本数据类型使用volatile

基本类型的对象用volatile修饰后,仍旧支持所有的操作(加、乘、赋值等)。但是,用户定义的非基本类型(class、struct、union)的对象被volatile修饰后,具有不同行为:

  • 只能调用volatile成员函数;即只能访问它的接口的子集。
  • 只能通过const_cast运算符转为没有volatile修饰的普通对象。即由此可以获得对类型接口的完全访问。
  • volatile性质会传递给它的数据成员。

代码如下
public class Singleton {
private static volatile Singleton instance=null;
private Singleton(){

}

//静态工厂方法
public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){

instance=new Singleton();
}
}
}
return instance;
}
}


package com.wanson.designpatten;

import java.util.Calendar;

public class Driver {
public static void main(String[] args) {
Singleton instance=Singleton.getInstance();
System.out.println(instance);
Singleton secondInstance=Singleton.getInstance();
System.out.println(secondInstance);
Calendar calendar1= Calendar.getInstance();
System.out.println(calendar1);
Calendar calendar2=Calendar.getInstance();
System.out.println(calendar2);
}

}








































以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章

常用代码片段

性能比较好的单例写法

片段作为 Android 中的单例

单例片段或保存网页视图状态

你熟悉的设计模式都有哪些?写出单例模式的实现代码

单例模式以及静态代码块