设计模式-单例模式
来源:互联网 发布:极乐净土秀太捏脸数据 编辑:程序博客网 时间:2024/06/05 10:54
单例模式
定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
应用场景
当需要保证类在虚拟机中的对象唯一性
创建多个实例浪费资源
多个实例由于多次调用而出现错误。
一般写工具类,线程池,缓存,数据库等可以使用
特点
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
设计思想
- 将构造方法限定为private避免了类在外部被实例化。
- 单例类中持有一个私有本类实例的引用。
- 定义一个公共的方法getInstance(),在同一个虚拟机范围内,Singleton的唯一实例只能通过该方法访问。
- 注意:事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效,此问题在此处不做讨论。
实现方式
一、懒汉式单例
public class Singleton { private Singleton() {} private static Singleton single = null; public static Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; } }
以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例。要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全。
1、在getInstance方法上加同步
public static synchronized Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; }
2、双重检查锁定
public class Singleton { private Singleton() {} private static volatile Singleton single = null; public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; }
3、静态内部类
public class Singleton { private Singleton (){} public static final Singleton getInstance() { return LazyHolder.INSTANCE; } // 静态内部类 private static class LazyHolder { private static final Singleton INSTANCE = new Singleton(); }}
和饿汉式类似,两者都是通过类装载机制来保证初始化实例的时候只有一个线程,从而避免线程安全问题。饿汉式的Singleton类被加载,就会实例化Singleton,而静态内部类这种,当Singleton类被加载时,不会立即实例化,调用getInstance方法,才会装载SingletonHolder类,从而完成Singleton的实例化。
二、饿汉式单例
public class Singleton { private Singleton() {} private static final Singleton single = new Singleton(); public static Singleton getInstance() { return single; } }
饿汉式在类加载的同时就已经实例化一个静态的对象供系统使用,所以天生是线程安全的。但是若没有使用到该实例,依然会加载,从而造成资源浪费。
三、枚举实现单例模式
public enum SingletonEnum { INSTANCE; private Singleton instance; SingletonEnum() { instance = new Singleton() } public Singleton getInstance() { return instance; }}
访问方式:SingletonEnum.INSTANCE.method();
INSTANCE即为SingletonEnum类型的引用,得到它就可以调用枚举中的方法。既避免了线程安全问题,还能防止反序列化重新创建新的对象,但是失去了类的一些特性,没有延时加载,推荐使用。
四、使用容器实现单例模式
public class SingletonManager { private static Map<String,Object> objMap = new HashMap<String,Object>(); private Singleton() { } 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); }}
将多种单例类型注入到一个统一的管理类中,在使用时根据key获取对象对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用 户隐藏了具体实现,降低了耦合度。
优缺点
优点:保持类对象唯一性,对于频繁创建和销毁的对象可以提高性能。
缺点:扩展困难,单例的方法无法生成子类对象,要扩展的话基本要重写这个类。
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 设计模式-单例模式
- [设计模式] 单例模式
- 设计模式--单例模式
- 设计模式---单例模式
- 设计模式--单例模式
- 设计模式 -----单例模式
- 设计模式:单例模式
- 【python 爬虫】selenium爬虫模块 phantomjs如何加代理IP
- struts2框架学习笔记02
- Java编程思想之字符串
- python基础--tuple()
- Jquery PlugIn for lazy loading items.
- 设计模式-单例模式
- 《战狼》背后的大数据分析
- 安装Sphinx 2.0.4时出现的以下几个错误处理方法 WARNING: compat_sphinxql_magics=1 is deprecated;
- Adb常用命令集合
- JDBC
- popupwindow
- HDU 2546饭卡 【01背包水题】
- linux oracle rac 备份到本地
- 头条号作者是怎么赚钱的?