二十三种设计模式(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)的主要内容,如果未能解决你的问题,请参考以下文章