设计模式之单例模式
来源:互联网 发布:效率最高的查找算法 编辑:程序博客网 时间:2024/05/17 06:03
单例模式,顾名思义一个类有且只有一个实例。
那怎么才能做到一个类只有一个实例呢?
(1)构造私有化
(2)实例静态成员化
(3)通过静态方法获得该实例
单例模式有很多种写法。
1.懒汉式
懒汉式是指需要该实例的时候才创建出该实例。
举个例子:小明下班回到家中,饿到实在不行,于是用烤箱做了一个面包吃。这是懒汉的表现。,不到饿的不行的时候不做饭吃。
下面看代码:
public class Bread{ public static Bread bread; //实例静态成员化 //构造私有化 private Bread() { } //静态方法获取实例 public static Bread getBread() { if (bread == null) { bread = new Bread(); //需要该实例的时候才创建 } return bread; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
2.饿汉式
饿汉式是指在类加载时就初始化好实例。
举个例子:小明下班回到家中,饿的不行,于是赶紧从冰箱中拿出早已做好得面包来吃。这是饿汉的表现,早早的准备好食物,生怕饿着自己。
下面看代码:
public class Bread { ////实例静态成员化,加载类的时候就初始化好该该实例 private static Bread bread = new Bread(); //构造私有化 private Bread() { } //静态方法获取实例 public static Bread getBread() { return bread; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
下面看Java API用到单例模式饿汉式的一个类:
Runtime类的源码
public class Runtime { private static Runtime currentRuntime = new Runtime(); public static Runtime getRuntime() { return currentRuntime; } private Runtime() {} ...}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
可以看到和上面的Bread类的写法是一样的。
饿汉式是开发中经常写的一种,因为它不容易出错,做的是原子操作(不会被线程调度机制打断的操作),不涉及多线程安全问题。而懒汉式在涉及多线程访问的时候会出错。比如:当线程A执行到if语句中并且还未创建bread对象时,另一个线程B也执行到if语句,这样就会创建两个bread实例。
这个时候菜鸟A问:那怎么改进这种写法呢?
菜鸟B回答:这还不简单,给这个方法加一个同步锁。代码如下:
public class Bread{ public static Bread bread; private Bread() { } public synchronized static Bread getBread() { if (bread == null) { bread = new Bread(); } return bread; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
3.双重锁定式
这个时候老鸟C听到了菜鸟B的回答,
呵呵道:真是年轻啊!
菜鸟B:怎么了,难道我写的不对?
老鸟C:写的不能说不对,只是你这样一来,每次执行该方法都要受到同步锁的影响,而本意是只有当创建bread实例时才要加同步锁,这样必然导致程序效率下降。于是老鸟露了一手,代码如下:
public class Bread { private static Bread bread; private Bread() { } public static Bread getBread() { if (bread == null) { synchronized (Bread.class) { if (bread == null) { bread = new Bread(); } } } return bread; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
这里面有两个if判断,首先第一个if判断是为了当且仅当创建该实例的时候才加同步锁,第二个if是为了防止这样的情况的发生:当线程A执行到第一个if,并进入同步代码块时,线程B也执行到第一个if的位置,因为比线程A慢了一步,于是需要等线程A释放所对象才能继续执行,当线程A实例好bread对象之后,倘若不加第二个if判断,线程B不知道bread是否已经实例化好,于是会紧接着再创建一个Bread实例。这样就会出错。
听完老鸟的讲解,菜鸟们恍然大悟。这就是双重锁定式的单例模式。
4.内部持有类式
这种写法和饿函数相似,都是类加载的时候初始化好实例,只不过这种写法是将初始化操作放在了内部类中。代码如下:
public class Bread { private Bread() { } private static class BreadHolder { private static Bread bread = new Bread(); } public static Bread getInstance() { return BreadHolder.bread; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
总结
单例模式保证了一个类只有一个实例,并提供全局访问该实例的方法。除了第一种写法,其他的写法都保证了多线程安全问题(多个类加载器和反射手段除外,不做考虑)。
转自:http://blog.csdn.net/Mr_Lawen/article/details/52235396
- 设计模式之 单例设计模式
- 设计模式之 单例设计模式
- 设计模式之单例设计模式
- 设计模式之-----------单例设计模式
- 设计模式之:单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之-单例设计模式
- 设计模式之单例设计模式 标签: 设计模式
- 设计模式之单例
- 设计模式之单例
- 设计模式之 单例
- 安装XAMPP时启动Apache失败解决方法 xampp
- Mac 批量删除 .svn 文件
- linux根文件系统 /etc/shadow文件详解
- smarty库路径出错
- GNU软件编译一般步骤
- 设计模式之单例模式
- 站在巨人的肩膀上,C++开源库大全
- FineReport打印方式(转)
- 关于el表达式用==和eq不准确一直判断为false的问题
- 高德地图定位
- CODE[VS] 1198【NOIP2012】 国王游戏(贪心
- cluster_check
- halcon启动文件的区别
- 第20天新手SEO基础计划之:Meta标记控制搜索结果