很长一段时间,根本区分不了各种设计模式。
工作过程中,经常用到单例模式,才算第一次了解一种设计模式
单例概念:确保某个类只有一个实例,并且自行实例化,并向整个系统提供该实例
为什么要使用单例模式呢?
记得开发工程中,打开相机页面这个ActiivtyCamera这个类,最初并没有被设计成单例模式,导致每次返回竟然返回2次才能关闭相机,创建了2个acitiviy页面,如果设计成单例模式就可避免该问题。
优点:
由于单例模式在内存中只有一个实例,减少了内存开销。
单例模式可以避免对资源的多重占用,例如读、写文件操作
单例模式可以在系统设置全局的访问点,优化和共享资源访问。
优点这么多,多的我也说不上来。。。。。
看了很多博客,说懒汉模式,或者饿汉模式都有缺点,那就看看双重检查锁定模式,直接上栗子。
private static $class$ m$class$ = null;
private $class$() {
}
public static $class$ getInstance() {
if (m$class$ == null) {
Synchronized($class$.class) {
if (m$class$ == null) {
m$class$ = new $class$;
}
}
}
return m$class$;
}
双重检查锁定模式:无非就是判空2次,并实现同步块,还有一种写法(volatile),对比一下:
public class Singleton { private volatile static Singleton instance = null; private Singleton(){ } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
2者区别仅在于volatile这个关键字,volative易变的。
构造函数私有,这个都知道,getInstance(),静态公有方法
volatile: 易变的,肯定是不容易确定的,这个就是告诉jvm 当前变量在寄存器中的值是不定的,需要从内存中读取,用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值。
Synchronized:同步,同步代码块用该关键字实现,在多线程访问的时候,同一时刻只能有一个线程访问用Synchronized修饰的代码块或者方法。不但保证了可见性还保证了原子性。可见性原子性我也傻傻分不清楚,自行百度。
再就是这个双重判断null :
这是因为如果线程A进入了该代码,线程B 在等待,这是A线程创建完一个实例出来后,线程B 获得锁进入同步代码,实例已经存在,木有必要再创建一个,所以双重判断有必要。(这个解释我服气)InputMethodManager类就是单例模式。
双重锁定模式优于懒汉模式,饿汉模式也行现在你明白了吗?不明白的接着看:
懒汉模式:栗子
package com.example.mytry; public class Util { private static Util instance; private Util() {} public static Util getInstance() { if (instance == null) { instance = new Util(); } return instance; } }
单例模式的懒汉式实现方式体现了延迟加载的思想。
什么是延迟加载呢?
哦,原来不是懒,是为了达到节约资源的目的。
那饿汉模式呢,怎么看怎么没差别啊?
package com.example.mytry; public class Util { private static final Util instance = new Util(); private Util() { } public static Util getInstance() { return instance; } }
饿汉式 static final field
这种方法非常简单,因为单例的实例被声明成 static 和 final 变量了,在第一次加载类到内存中时就会初始化,所以创建实例本身是线程安全的。饿汉式的创建方式在一些场景中将无法使用。
http://blog.csdn.net/nsw911439370/article/details/50456231 此博客讲的比较详细,可参考!
1:时间和空间
比较上面两种写法:懒汉式是典型的时间换空间,也就是每次获取实例都会进行判断,看是否需要创建实例,费判断的时间,当然,如果一直没有人使用的话,那就不会创建实例,节约内存空间。
饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间。
2: 线程安全
从线程安全性上讲,不加同步的懒汉式是线程不安全的,比如说:有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,那就可能导致并发问题