二十三种设计模式(GOF23)详解1----单例模式(Singleton Pattern)

Posted Java学习成神之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二十三种设计模式(GOF23)详解1----单例模式(Singleton Pattern)相关的知识,希望对你有一定的参考价值。

单例模式的定义:
   Ensure a class has only one instance,and provide a global point of access to is.
   保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

单例模式通用类图

单例模式通用代码:

 1            public class Singleton {
2
3                    //静态放法类初始化时生成实例,线程安全
4
5                    private static final Singleton singleton = new Singleton();
6
7                    //构造方法私有化,禁止其他方式产生实例
8
9                    private Singleton(){}
10
11                    //通过该方法获得实例对象
12
13                    public static Singleton getSingleton(){
14
15                            return singleton;
16
17                        }
18
19                    //类中其他方法,尽量是static
20
21                    public static void doSomething(){}
22
23                }

单例模式的优点:

  • 由于单例模式只生成一个实例,减少了系统性能的开销,当一个对象的产生需要比较多的资源时,如何读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

  • 单例模式可以在系统设置全局的访问点,优化共享资源访问。

常见的五种单例模式及其实现方式:

主要:

  • 饿汉式(线程安全,调用效率高,不能延时加载)

  • 懒汉式(线程安全,调用效率不高,可以延时加载)

其他:

  • 双重检测锁式(由于JVM底层内部模式原因,存在问题,不建议使用)

  • 静态内部类式(线程安全,调用效率高,可以延时加载)

  • 枚举(线程安全,调用效率高,不能延时加载)

饿汉式实现方法

1public class SingletonDemo02 {
2
3   private static SingletonDemo02 s = new SingletonDemo02();
4   private SingletonDemo02(){}
5   public static SingletonDemo02 getInstance(){
6       return s;
7   }
8}                    

饿汉式实例为static变量,会在类装载时初始化,不存在多个线程访问该对象的问题,因为虚拟机只会装在一次改类。如果只是加载本类而不去调用getInstance()方法时,会造成资源的浪费

懒汉式实现方法

 1public class SingletonDemo01 {
2   private static SingletonDemo01 s;
3   private SingletonDemo01(){}
4   public static synchronized SingletonDemo01 getInstance(){
5       if (s == null){
6           s = new SingletonDemo01();
7       }
8       return s;
9   }
10}

只有在用时才会加载,但是,每次调用getInstance()方法时都要同步,影响效率.

双重检测锁实现方法

 1public class SingletonDemo03 {
2
3    private  static SingletonDemo03 s = null;
4
5    public static SingletonDemo03 getInstance(){
6        if (s == null){
7            SingletonDemo03 sc ;
8            synchronized (SingletonDemo03.class){
9                sc = s;
10                if (sc == null){
11                    synchronized (SingletonDemo03.class){
12                        if (sc == null){
13                            sc = new SingletonDemo03();
14                        }
15                    }
16                    s = sc;
17                }
18            }
19        }
20
21        return s;
22    }
23    private SingletonDemo03(){}
24}
1 

将同步内容放到if内部,只有第一次调用时才会同步。由于JAVA内存模型原因,偶尔会出现问题,可在静态变量前加  volatile 修饰

静态内部类实现方法

1public class SingletonDemo04 {
2   private static class SingletonClassInstance{
3       private static final SingletonDemo04 s = new SingletonDemo04();
4   }
5   private SingletonDemo04(){}
6   public static SingletonDemo04 getInstance(){
7       return SingletonClassInstance.s;
8   }
9}

JVM加载本体类时,内部静态类不会一同加载,只有调用getInstance()方法时才会加载静态内部类,instance是static final保证内存中只有一个实例存在,且只能被赋值一次,保证线程安全.

枚举类实现方法

1public enum SingletonDemo05 {
2   INSTANCE;
3}

枚举本身就是天然单例模式。

实际测试代码:

 1//懒汉式
2SingletonDemo01 s1 =SingletonDemo01.getInstance();
3SingletonDemo01 s2 =SingletonDemo01.getInstance();
4//饿汉式
5SingletonDemo02 s3 =SingletonDemo02.getInstance();
6SingletonDemo02 s4 =SingletonDemo02.getInstance();
7//静态内部类
8SingletonDemo04 s7 =SingletonDemo04.getInstance();
9SingletonDemo04 s8 =SingletonDemo04.getInstance();
10//枚举类
11SingletonDemo05 s9 =SingletonDemo05.INSTANCE;
12SingletonDemo05 s10 =SingletonDemo05.INSTANCE;
13
14System.out.println("懒汉式:"+ (s1 == s2) );//true
15System.out.println("饿汉式:"+(s3 == s4));//true
16System.out.println("静态内部类:"+(s7 == s8 ));//true
17System.out.println("枚举类:"+(s9 == s10 ));//true


以上是关于二十三种设计模式(GOF23)详解1----单例模式(Singleton Pattern)的主要内容,如果未能解决你的问题,请参考以下文章

二十三种设计模式 罗列

[系列汇总] - 二十三种设计模式(持续更新中…)

史上最全的二十三种设计模式总结

二十三种设计模式[23] - 访问者模式(Visitor Pattern)

Java 面试之单例模式

二十三种设计模式及其python实现