应用最广的设计模式——单例模式
- 介绍
单例模式是应用最广的模式之一,也可能是很多初级工程师唯一会使用的设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需拥有一个全局对象,这样有利于我们协调系统整体的行为。
- 定义
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例
- 使用场景
确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。例如,创建一个对象需要消耗的资源过多,需要访问IO和数据库等资源。
- 代码实现
饿汉单例模式:生命静态对象时就已经初始化instance,但是可能不需要它初始化,我们更希望在使用到单例的时候再初始化。
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
懒汉单例模式:在第一次调用getInstance时才初始化instance。但是第一次初始化之后,每次调用都会进行同步,这样会消耗不必要的资源。
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null)
instance = new Singleton();
return instance;
}
}
Double Check Lock(DCL):优点是既能够在需要时才初始化单例,又能够确保线程安全,且单例对象初始化后调用getInstance不进行同步锁。但是由于指令重排序问题,所以DCL会失效(解决方式可以为instance加上volatile关键字,从而禁止指令重排序)。
public class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) instance = new Singleton(); } } return instance; } }
静态内部类单例模式:最推荐使用的单例模式。第一次加载Singleton类时并不会初始化instance,只有在第一次调用Singleton的getInstance方法时才会导致instance被初始化。因此,第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,这种方式不仅能够保证线程安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化。
public class Singleton { private Singleton() { } public static Singleton getInstance() { return SingletonHolder.instance; } private static class SingletonHolder { private static final Singleton instance = new Singleton(); } }
使用容器实现单例模式:在程序的初始,将多种单例类型注入到一个统一的管理类中,在使用时根据key获取对象对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。
import java.util.HashMap; import java.util.Map; public class SingletonManager { private static Map<String, Object> objMap = new HashMap<>(); private SingletonManager() { } 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); } }
原文地址:https://www.cnblogs.com/zty-lyq/p/11561394.html
- 域名fde.com在国内平台以11万元被秒
- 微信小程序助力实体店对接互联网市场
- PostgreSQL 与 MySQL 相比,优势何在?
- Setting Up KeePass For Centos 6
- 拼音米大热!快视”、“冰冰”等多个域名结拍
- 入门必读:Hadoop新手学习指导
- 使用密码记录工具keepass来保存密码
- 机器人带着VR学习,最后学会了人工智能
- 超经典的JBOSS入门文章
- ASP.NET2.0应用中定制安全凭证
- AI造的AI,比人造的还厉害,该喜还是该忧?
- Mono 3.2 测试NPinyin 中文转换拼音代码
- Reactive Extensions介绍
- Reactive Extensions(Rx) 学习
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法