设计模式总结篇系列:单例模式(SingleTon)-阿里云开发者社区

开发者社区> 开发与运维> 正文

设计模式总结篇系列:单例模式(SingleTon)

简介:

在Java设计模式中,单例模式相对来说算是比较简单的一种构建模式。适用的场景在于:对于定义的一个类,在整个应用程序执行期间只有唯一的一个实例对象。如Android中常见的Application对象。

通过单例模式,自行实例化并向这个系统提供这个单一实例的访问方法。

根据此单一实例产生的时机不同(当然,都是指第一次,也是唯一一次产生此单一实例时),可以将其分为懒汉式、饿汉式和登记式。

一、懒汉式:

其特点是延迟加载,即当需要用到此单一实例的时候,才去初始化此单一实例。常见经典的写法如下:

复制代码
 1 package com.qqyumidi;
 2 
 3 public class SingleTon {
 4 
 5     // 静态实例变量
 6     private static SingleTon instance;
 7 
 8     // 私有化构造函数
 9     private SingleTon() {
10 
11     }
12 
13     // 静态public方法,向整个应用提供单例获取方式
14     public static SingleTon getInstance() {
15         if (instance == null) {
16             instance = new SingleTon();
17         }
18         return instance;
19     }
20 
21 }
复制代码

 

懒汉式的线程安全写法

复制代码
 1 package com.qqyumidi;
 2 
 3 public class SingleTon {
 4 
 5     // 静态实例变量加上volatile
 6     private static volatile SingleTon instance;
 7 
 8     // 私有化构造函数
 9     private SingleTon() {
10 
11     }
12 
13     // 双重检查锁
14     public static SingleTon getInstance() {
15         if (instance == null) {
16             synchronized(Singleton.class){
17                 if(instance == null){
18                     instance = new SingleTon();
19                 }
20             }
21         }
22         return instance;
23     }
24 
25 }
复制代码

 

 

二、饿汉式:

饿汉式的特点是应用中尚未需要用到此单一实例的时候即先实例化。常见的经典写法为:

复制代码
 1 package com.qqyumidi;
 2 
 3 public class SingleTon {
 4 
 5     // 静态实例变量,直接初始化
 6     private static SingleTon instance = new SingleTon();
 7 
 8     // 私有化构造函数
 9     private SingleTon() {
10 
11     }
12 
13     // 静态public方法,向整个应用提供单例获取方式
14     public static SingleTon getInstance() {
15         return instance;
16     }
17 
18 }
复制代码

 

三、登记式单例模式:

登记式单例模式,一般是通过一个专门的类对各单例模式的此单一实例进行管理和维护。通过Map方式可以方便的实现此中目的。常见的代码如下:

复制代码
 1 package com.qqyumidi;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 public class SingleTonManager {
 7 
 8     private static Map singleTonMap = new HashMap();
 9 
10     public static void main(String[] args) {
11         // 获取A类的单例
12         A a = (A) getInstance(A.class.getName());
13         // 获取B类的单例
14         B b = (B) getInstance(B.class.getName());
15     }
16 
17     // 根据类型获取单例
18     public static Object getInstance(String className) {
19         // 判断singleTonMap中是否有此单例,有则取得后返回,无则添加单例后返回
20         if (!singleTonMap.containsKey(className)) {
21             try {
22                 singleTonMap.put(className, Class.forName(className).newInstance());
23             } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
24                 // TODO Auto-generated catch block
25                 e.printStackTrace();
26             }
27         }
28         return singleTonMap.get(className);
29     }
30 }
31 
32 class A {
33 
34 }
35 
36 class B {
37 
38 }
复制代码

 

另外:需要注意的是,在多线程环境中,以上各种方法构造单例模式需要考虑到线程安全问题。

 

四、改进型懒汉式(直接满足线程安全)——通过静态内部类实现

在如上的懒汉单例模式中,对于多线程环境中。可以通过常见的如synchronized等方式实现线程安全,同时,可以通过Java静态内部类的方式实现进一步改进。

常见代码如下:

 

复制代码
 1 package com.qqyumidi;
 2 
 3 public class SingleTon {
 4 
 5     // 利用静态内部类特性实现外部类的单例
 6     private static class SingleTonBuilder {
 7         private static SingleTon singleTon = new SingleTon();
 8     }
 9 
10     // 私有化构造函数
11     private SingleTon() {
12 
13     }
14 
15     public static SingleTon getInstance() {
16         return SingleTonBuilder.singleTon;
17     }
18 
19     public static void main(String[] args) {
20         SingleTon instance = getInstance();
21     }
22 }
复制代码

 

其主要原理为:Java中静态内部类可以访问其外部类的成员属性和方法,同时,静态内部类只有当被调用的时候才开始首次被加载,利用此特性,可以实现懒汉式,在静态内部类中静态初始化外部类的单一实例即可。

 

---------------------------------------------------------------------------------
笔者水平有限,若有错漏,欢迎指正,如果转载以及CV操作,请务必注明出处,谢谢!
分类: 设计模式

本文转自Windstep博客园博客,原文链接:http://www.cnblogs.com/lwbqqyumidi/p/3738059.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章