博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【设计模式系列】单例模式的7种写法
阅读量:6159 次
发布时间:2019-06-21

本文共 3369 字,大约阅读时间需要 11 分钟。

前言

单例模式是一种常用的软件设计模式,在他的核心结构中只包含一个被称为 单例的特殊类。通过单例模式可以保证系统只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。 

Singletom类,定义一个GetInstance操作,允许客户访问他的唯一实例,GetInstance是一个静态方法,主要负责创建自己的唯一实例。

一、实现

1、饿汉式

public class Singleton {        private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance(){             return singleton;         }  }

优点:在类加载时就完成了对象的初始化,所以类加载比较慢,但是获取对象的速度比较快。

缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。

2、懒汉式(线程不安全)

public class Singleton {        private static Singleton singleton ;
private Singleton() {}
public static Singleton getInstance(){                 if(singleton == null){          singleton = new Singleton();          }     return singleton;    } }  

优点:这种写法起到了延迟加载的效果,但是只能在单线程下使用。

缺点:如果在多线程下,一个线程进入了if(singleton == null )判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可以使用这种方式。

3、懒汉式(线程安全)

public class Singleton {        private static Singleton singleton ;        public static Singleton getInstance(){            synchronized (Singleton.class) {            if(singleton == null){                    singleton = new Singleton();                }            }            return singleton;        }}  

或者

public class Singleton {        private static Singleton singleton ;         private Singleton(){}        public synchronized static Singleton getInstance(){            if(singleton == null){                    singleton = new Singleton();                }            return singleton;        }}  

优点:解决了上面线程不安全的问题

缺点:效率太低,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步,而其实这个方法只执行一次实例化代码六够了,后面的想获得该实例,直接return就就好了。方法进行同步效率太低。

4、双重检查式(DCL:Double-checked locking)

public class Singleton {    private static Singleton singleton;    public static Singleton getInstance() {        if (singleton == null) {            synchronized (Singleton.class) {                if (singleton == null) {                    singleton = new Singleton();                }            }        }        return singleton;    }}  

优点:线程安全、延迟加载、效率较高。

这种写法在getInstance()方法中进行了两次空判断,第一次是为了避免不必要的同步,第二次是在singleton为空的情况下才创建实例。DCL虽然在一定程度上解决了资源的消耗和多余的同步,线程安全等问题,但是在某些情况下会出现DCL失效。有些书中建议使用静态内部类单例模式来代理DCL。

5、静态内部类单例模式

public class Singleton {    public static Singleton getInstance() {        return SingletonHolder.singleton;    }    private static class SingletonHolder {        private static final Singleton singleton = new Singleton();    }}  

加载一个类时,其内部的类不会同时被加载,当且仅当某个静态成员(静态成员变量、构造方法、静态方法)被调用时才去加载。第一次加载Singleton时并不会初始化Singleton,只有第一次调用getInstance()方法时才会加载SingletonHolder,并且初始化Singleton,这样不仅能够保证线程的安全性也能保证Singleton类的唯一性。推荐使用中这种方式。

6、枚举单例

public enum Singleton{        INSTANCE;        public void doSomething(){        }}  

优点:通过Singleton.INSTANCE来访问,比较方便,线程安全,防止反序列化创建新的对象,

缺点:失去了一些类的特性,没有延迟加载,可读性差

7、容器式

public class SingletonManager {        public static Map
objMap = new HashMap
(); public static void registerService(String key,Object instance){ if(!objMap.containsKey(key)){ objMap.put(key, instance); } } public static Object getService(String key){ return objMap.get(key); }}  

 用SingletonManager将多个单例统一进行管理,使用时根据key获取对应的实例,这种方式可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,屏蔽了内部实现细节,降低了耦合度。 

转载于:https://www.cnblogs.com/dream-to-pku/p/9176072.html

你可能感兴趣的文章
25个常用的Linux iptables规则
查看>>
集中管理系统--puppet
查看>>
Exchange 2013 PowerShell配置文件
查看>>
JavaAPI详解系列(1):String类(1)
查看>>
HTML条件注释判断IE<!--[if IE]><!--[if lt IE 9]>
查看>>
发布和逸出-构造过程中使this引用逸出
查看>>
使用SanLock建立简单的HA服务
查看>>
Subversion使用Redmine帐户验证简单应用、高级应用以及优化
查看>>
Javascript Ajax 异步请求
查看>>
DBCP连接池
查看>>
cannot run programing "db2"
查看>>
mysql做主从relay-log问题
查看>>
Docker镜像与容器命令
查看>>
批量删除oracle中以相同类型字母开头的表
查看>>
Java基础学习总结(4)——对象转型
查看>>
BZOJ3239Discrete Logging——BSGS
查看>>
SpringMVC权限管理
查看>>
spring 整合 redis 配置
查看>>
cacti分组发飞信模块开发
查看>>
浅析LUA中游戏脚本语言之魔兽世界
查看>>