单例模式

Posted linbq1911

tags:

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

1.定义:保证一个类仅有一个实例,并提供一个全局访问点。

2.类型:创建型

3.适用场景:想确保任何情况下都绝对只有一个实例。

4.优点:在内存里只有一个实例,减少了内存开销;
    可以避免对资源的多重占用;
    设置全局访问点,严格控制访问。

5.缺点:没有接口,扩展困难

6.重点:私有构造器、线程安全、延迟加载、序列化和反序列化安全、反射

7.实用技能:反编译、内存原理、多线程Debug

8.相关设计模式:工厂模式、享元模式

9.实例目录package

技术分享图片

10.实例UML类图

技术分享图片

11.代码

 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 import java.io.Serializable;
 4 
 5 public class HungrySingleton implements Serializable,Cloneable {
 6     private final static HungrySingleton hungrySingleton;
 7     static{
 8         hungrySingleton = new HungrySingleton();
 9     }
10     private HungrySingleton(){
11         if(hungrySingleton != null){
12             throw new RuntimeException("单例构造器禁止反射调用");
13         }
14     }
15     public static HungrySingleton getInstance(){
16         return hungrySingleton;
17     }
18 
19     private Object readResolve(){
20         return hungrySingleton;
21     }
22 
23     @Override
24     protected Object clone() throws CloneNotSupportedException {
25         return getInstance();
26     }
27 }
 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Field;
 5 
 6 public class LazySingleton {
 7     private static LazySingleton lazySingleton = null;
 8     private static boolean flag = true;
 9     private LazySingleton(){
10         if(flag){
11             flag = false;
12         }else{
13             throw new RuntimeException("单例构造器禁止反射调用");
14         }
15         /*if(lazySingleton != null){
16             throw new RuntimeException("单例构造器禁止反射调用");
17         }*/
18     }
19     public synchronized static LazySingleton getInstance(){
20         //synchronized(LazySingleton.class){
21             if(lazySingleton == null){
22                 lazySingleton = new LazySingleton();
23             }
24        // }
25         return lazySingleton;
26     }
27 
28     public static void main(String[] args) throws Exception{
29         Class objectClass = LazySingleton.class;
30         //Class.forName(HungrySingleton.class.getName());
31         Constructor constructor = objectClass.getDeclaredConstructor();
32         constructor.setAccessible(true);
33 
34         LazySingleton instance = LazySingleton.getInstance();
35         Field flag = instance.getClass().getDeclaredField("flag");
36         flag.setAccessible(true);
37         flag.set(instance,true);
38         LazySingleton newInstance = (LazySingleton) constructor.newInstance();
39 
40         System.out.println(instance);
41         System.out.println(newInstance);
42         System.out.println(instance == newInstance);
43     }
44 }
 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 public class LazyDoubleCheckSingleton {
 4     private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;
 5     private LazyDoubleCheckSingleton(){
 6 
 7     }
 8     public static LazyDoubleCheckSingleton getInstance(){
 9         if(lazyDoubleCheckSingleton == null){
10             synchronized (LazyDoubleCheckSingleton.class){
11                 if(lazyDoubleCheckSingleton == null){
12                     lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
13                     //1.分配内存给这个对象
14                     //2.初始化对象
15                     //3.设置lazyDoubleCheckSingleton指向刚分配的内存地址
16                     // intra-thread semantics
17                     //2和3可能调换顺序
18                 }
19             }
20         }
21         return lazyDoubleCheckSingleton;
22     }
23 }
 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 public class StaticInnerClassSingleton {
 4     private static class InnerClass{
 5         private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
 6     }
 7     public static StaticInnerClassSingleton getInstance(){
 8         return InnerClass.staticInnerClassSingleton;
 9     }
10 
11     private StaticInnerClassSingleton(){
12         if(InnerClass.staticInnerClassSingleton != null){
13             throw new RuntimeException("单例构造器禁止反射调用");
14         }
15     }
16 }
 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 import org.apache.commons.lang.StringUtils;
 4 
 5 import java.util.HashMap;
 6 import java.util.Map;
 7 
 8 public class ContainerSingleton {
 9     private ContainerSingleton(){}
10     private static Map<String, Object> singletonMap = new HashMap<>();
11 
12     public static void putInstance(String key,Object instance){
13         if(StringUtils.isNotBlank(key) && instance != null){
14             if(!singletonMap.containsKey(key)){
15                 singletonMap.put(key,instance);
16             }
17         }
18     }
19     public static Object getInstance(String key){
20         return singletonMap.get(key);
21     }
22     
23 }
 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 public class ThreadLocalInstance {
 4     private static final ThreadLocal<ThreadLocalInstance> threadLocalInstanceThreadLocal
 5             = new ThreadLocal<ThreadLocalInstance>(){
 6         @Override
 7         protected ThreadLocalInstance initialValue() {
 8             return new ThreadLocalInstance();
 9         }
10     };
11 
12     private ThreadLocalInstance(){}
13     public static ThreadLocalInstance getInstance(){
14         return threadLocalInstanceThreadLocal.get();
15     }
16     
17 }
 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 public enum EnumInstance{
 4     INSTANCE{
 5         protected void printTest(){
 6             System.out.println("Geely Print Test");
 7         }
 8     };
 9     protected abstract void printTest();
10     private Object data;
11 
12     public Object getData() {
13         return data;
14     }
15 
16     public void setData(Object data) {
17         this.data = data;
18     }
19     public static EnumInstance getInstance(){
20         return INSTANCE;
21     }
22 }
 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 public class T implements Runnable {
 4     @Override
 5     public void run() {
 6         //LazySingleton instance = LazySingleton.getInstanc();
 7         //LazyDoubleCheckSingleton instance = LazyDoubleCheckSingleton.getInstance();
 8         //StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
 9         //ContainerSingleton.putInstance("object",new Object());
10         //Object instance = ContainerSingleton.getInstance("object");
11         ThreadLocalInstance instance = ThreadLocalInstance.getInstance();
12         System.out.println(Thread.currentThread().getName() + ":  "+instance);
13     }
14 }
 1 package com.geely.design.pattern.creational.singleton;
 2 
 3 import java.io.*;
 4 import java.lang.reflect.Constructor;
 5 import java.lang.reflect.Method;
 6 
 7 public class Test {
 8     public static void main(String[] args) throws Exception {
 9         //LazySingleton lazySingleton = LazySingleton.getInstanc();
10         //System.out.println(lazySingleton);
11 
12         /*Thread t1 = new Thread(new T());
13         Thread t2 = new Thread(new T());
14         t1.start();
15         t2.start();*/
16 
17 //        HungrySingleton instance = HungrySingleton.getInstance();
18 //        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
19 //        oos.writeObject(instance);
20 //        File file = new File("singleton_file");
21 //        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
22 //        HungrySingleton newInstance = (HungrySingleton)ois.readObject();
23 //        System.out.println(instance);
24 //        System.out.println(newInstance);
25 //        System.out.println(instance == newInstance);
26 
27 //        Class objectClass = HungrySingleton.class;
28 //        //Class.forName(HungrySingleton.class.getName());
29 //        Constructor constructor = objectClass.getDeclaredConstructor();
30 //        constructor.setAccessible(true);
31 //        HungrySingleton instance = HungrySingleton.getInstance();
32 //        HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();
33 //        System.out.println(instance);
34 //        System.out.println(newInstance);
35 //        System.out.println(instance == newInstance);
36 
37 //        Class objectClass = StaticInnerClassSingleton.class;
38 //        //Class.forName(HungrySingleton.class.getName());
39 //        Constructor constructor = objectClass.getDeclaredConstructor();
40 //        constructor.setAccessible(true);
41 //        StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
42 //        StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();
43 //        System.out.println(instance);
44 //        System.out.println(newInstance);
45 //        System.out.println(instance == newInstance);
46 
47 //        Class objectClass = LazySingleton.class;
48 //        //Class.forName(HungrySingleton.class.getName());
49 //        Constructor constructor = objectClass.getDeclaredConstructor();
50 //        constructor.setAccessible(true);
51 //        LazySingleton newInstance = (LazySingleton) constructor.newInstance();
52 //        LazySingleton instance = LazySingleton.getInstance();
53 //
54 //        System.out.println(instance);
55 //        System.out.println(newInstance);
56 //        System.out.println(instance == newInstance);
57 
58 //        EnumInstance instance = EnumInstance.getInstance();
59 //        instance.setData(new Object());
60 //        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
61 //        oos.writeObject(instance);
62 //        File file = new File("singleton_file");
63 //        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
64 //        EnumInstance newInstance = (EnumInstance)ois.readObject();
65 //        System.out.println(instance.getData());
66 //        System.out.println(newInstance.getData());
67 //        System.out.println(instance.getData() == newInstance.getData());
68 
69 //        Class objectClass = EnumInstance.class;
70 //        //Class.forName(HungrySingleton.class.getName());
71 //        Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
72 //        constructor.setAccessible(true);
73 //        EnumInstance newInstance = (EnumInstance) constructor.newInstance("Geely",666);
74 //        EnumInstance instance = EnumInstance.getInstance();
75 //        System.out.println(instance);
76 //        System.out.println(newInstance);
77 //        System.out.println(instance == newInstance);
78 
79 //        EnumInstance instance = EnumInstance.getInstance();
80 //        instance.printTest();
81 
82         HungrySingleton hungrySingleton = HungrySingleton.getInstance();
83         Method method = hungrySingleton.getClass().getDeclaredMethod("clone");
84         method.setAccessible(true);
85         HungrySingleton cloneHungrySingletion = (HungrySingleton)method.invoke(hungrySingleton);
86         System.out.println(hungrySingleton);
87         System.out.println(cloneHungrySingletion);
88         System.out.println("program end");
89     }
90 }

 



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

常用代码片段

性能比较好的单例写法

片段作为 Android 中的单例

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

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

单例模式以及静态代码块