码迷,mamicode.com
首页 > 其他好文 > 详细

GOF23设计模式之单例模式(singleton)

时间:2017-12-23 18:58:09      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:leo   singleton   rgs   file   构造   stat   post   tin   syn   

一、单例模式概述

  保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

二、单例模式的五种写法

  1.饿汉式

    优点:线程安全,效率高

    缺点:无法延时加载

 1 public class Singleton {
 2     
 3     private static Singleton instance = new Singleton();
 4     
 5     //私有化构造器
 6     private Singleton() {}
 7 
 8     //提供全局访问点
 9     public static Singleton getInstance() {
10         return instance;
11     }
12     
13 }
 1 public class Singleton {
 2     
 3     private static Singleton instance = null;
 4     
 5     static {
 6         instance = new Singleton();
 7     }
 8     
 9     //私有化构造器
10     private Singleton() {}
11 
12     //提供全局访问点
13     public static Singleton getInstance() {
14         return instance;
15     }
16     
17 }

  2. 懒汉式

    优点:线程安全,延时加载

    缺点:效率较低

    (1)非线程安全

 1 public class Singleton {
 2     
 3     private static Singleton instance;
 4     
 5     //私有化构造器
 6     private Singleton() {}
 7 
 8     //提供一个全局的访问点
 9     public static Singleton getInstance() {
10         if (instance == null) {
11             instance = new Singleton();
12         }
13         return instance;
14     }
15     
16 }

    (2)线程安全

 1 public class Singleton {
 2     
 3     private static Singleton instance;
 4     
 5     //私有化构造器
 6     private Singleton() {}
 7 
 8     //使用同步方法获取该类对象
 9     public static synchronized Singleton getInstance() {
10         if (instance == null) {
11             instance = new Singleton();
12         }
13         return instance;
14     }
15     
16 }
 1 public class Singleton {
 2     
 3     private static Singleton instance;
 4     
 5     //私有化构造器
 6     private Singleton() {}
 7 
 8     //使用同步块获取该类对象
 9     public static Singleton getInstance() {
10         synchronized (Singleton.class) {
11             if (instance == null) {
12                 instance = new Singleton();
13             }
14             return instance;
15         }
16     }
17     
18 }

  3.双重检查锁

    注意:由于编译器优化和JVM底层内部模型原因,偶尔会出问题,不建议使用

    优点:线程安全,延时加载

    缺点:效率较低,会出错误

 1 public class Singleton {
 2     
 3     private static Singleton instance;
 4     
 5     private Singleton() {}
 6     
 7     //第一次判断是为了避免不必要的同步,第二次判断是属性为null时创建实例
 8     public static Singleton getInstance() {
 9         if (instance == null) {
10             synchronized (Singleton.class) {
11                 if (instance == null) {
12                     instance = new Singleton();
13                 }
14             }
15         }
16         return instance;
17     }
18 
19 }

  4.静态内部类式

    不调用静态方法不加载内部类,延缓加载(懒加载),提高效率

    优点:线程安全,延时加载,效率高

 1 public class Singleton {
 2     
 3     //静态内部类
 4     private static class SingletonHolder {
 5         //final可加可不加,因为外部类的外部无法使用该内部类
 6         private static /*final*/ Singleton instance = new Singleton();
 7     }
 8     
 9     //私有化构造器
10     private Singleton() {}
11 
12     //提供一个全局的访问点
13     public static Singleton getInstance() {
14         return SingletonHolder.instance;
15     }
16     
17 }

  5.枚举

    注意:建议使用

    优点:实现简单,线程安全,效率高,由于JVM从根本上实现保障,避免反射和反序列化的漏洞

    缺点:无延时加载

1 1 public enum Singleton {
2 2     //这个枚举元素,本身就是一个单例对象
3 3     INSTANCE;
4 4 }

三、破解单例模式 

  1.使用反序列化破解单例对象

 1 import java.io.ObjectStreamException;
 2 import java.io.Serializable;
 3 
 4 /**
 5  * 使用反序列化破解单例模式
 6  * @author 曹磊
 7  *
 8  */
 9 public class Singleton implements Serializable {
10     
11     private static Singleton instance;
12     
13     private Singleton() {}
14 
15     //使用同步方法获取该类对象
16     public static synchronized Singleton getInstance() {
17         if (instance == null) {
18             instance = new Singleton();
19         }
20         return instance;
21     }
22     
23     //反序列化时,如果创建了readResolve()方法则直接返回已经创建好的对象,而不需要再重新创建新的对象
24     private Object readResolve() throws ObjectStreamException {
25         return instance;
26     }
27     
28 }
 1 import java.io.FileInputStream;
 2 import java.io.FileOutputStream;
 3 import java.io.ObjectInputStream;
 4 import java.io.ObjectOutputStream;
 5 
 6 /**
 7  * 测试反序列化破解单例模式
 8  * @author 曹磊
 9  *
10  */
11 public class TestSingleton {
12     
13     public static void main(String[] args) throws Exception {
14         //先获得一个对象
15         Singleton s01 = Singleton.getInstance();
16         System.out.println("先获取的对象:" + s01);
17         
18         //(1)使用序列化将对象写出到系统文件
19         String filePath = "C:\\file\\obj.txt";
20         ObjectOutputStream oos = new ObjectOutputStream(
21                 new FileOutputStream(filePath));
22         oos.writeObject(s01);
23         oos.flush();
24         oos.close();
25         
26         //(2)使用反序列化读取文件中的对象
27         ObjectInputStream ois = new ObjectInputStream(
28                 new FileInputStream(filePath));
29         Singleton s02 = (Singleton) ois.readObject();
30         ois.close();
31         
32         System.out.println("反序列化读取的对象:" + s02);
33     }
34 
35 }

  控制台输出:

先获取的对象:com.caolei.singleton.Singleton@15db9742
反序列化读取的对象:com.caolei.singleton.Singleton@15db9742

GOF23设计模式之单例模式(singleton)

标签:leo   singleton   rgs   file   构造   stat   post   tin   syn   

原文地址:http://www.cnblogs.com/cao-lei/p/8085529.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!