GOF设计模式之单例模式
定义
单例模式(Singleton Pattern)的定义如下:Ensure a class only has one instance, and provide a global point of access to it(确保某一个类只有一个实例,并且提供一个全局访问点来访问此实例)。在JVM应用中,单例模式表现为一个类在JVM中只有一个实例。一个相对合理的类图如下:

使用场景
- 1、系统中需要一个共享的访问点或者共享数据,例如Web请求计数器。
- 2、创建一个对象需要消耗的资源过多,例如IO、数据库资管等。
- 3、需要定义大量的静态常量或者静态方法(例如工具类),可以考虑采用单例模式。
在JDK中典型的真实例子如下:
- java.lang.Runtime#getRuntime()
- java.awt.Desktop#getDesktop()
- java.lang.System#getSecurityManager()
适用性
单例模式的优势
- 采用单例模式的类能确保在一个应用中只有一个实例,减少了内存消耗以及创建或者销毁类实例时候的性能损耗。
- 可以避免对资源的多重占用。
- 可以设置应用的全局访问点,优化和共享资源访问。
单例模式的劣势
- 单例模式一般没有接口或者基类,扩展困难,扩展必须修改类代码。
- 紧密耦合的代码,对测试不利,简单来说就是不能Mock掉。
- 单例模式违反单一责任原则,因为它既要保持"单例"又要顾及业务逻辑。
实现方式
懒汉方式
懒汉方式的关键字在于"懒",也就是懒加载(Lazy Load),一个很常见的使用方式就是双重检查锁定(Double-Check Locking):
public class Singleton {
private static volatile Singleton INSTANCE = null;
private Singleton(){
}
public static Singleton getInstance(){
if (null == INSTANCE){
synchronized (Singleton.class){
if (null == INSTANCE){
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
饿汉方式
饿汉方式的实现相对简单:
public class Singleton {
private static volatile Singleton INSTANCE = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return INSTANCE;
}
}
静态内部类方式
使用静态内部类方式的好处是既可以实现延迟加载,又可以保证线程安全,它的实现如下:
public class Singleton {
private Singleton(){
}
private static class InterClassHolder{
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return InterClassHolder.INSTANCE;
}
}
最佳实践-单元素枚举方式
《Effective Java》第2版中指出:单元素枚举类型是实现单例的最佳方式。这是因为,前面说到的三种实现方式都可以通过反射改变类的行为,但是枚举类型可以避免这个问题。建议在所有需要使用到单例模式的情况下直接使用单元素枚举方式实现单例:
public enum Singleton {
INSTANCE;
public void sayHello() {
}
}
使用方式:Singleton.INSTANCE.sayHallo()。
故事
Doge是公司里一个核心项目的开发组长,手下有十多个组员分别负责开发项目的不同模块。


Doge展示了一个日期工具类和它的使用情况:
public class DateUtils {
public static String format(LocalDateTime target,String pattern){
return DateTimeFormatter.ofPattern(pattern).format(target);
}
public LocalDateTime parse(String target,String pattern){
return LocalDateTime.parse(target, DateTimeFormatter.ofPattern(pattern));
}
}
//调用情况
DateUtils.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss");
LocalDateTime target = new DateUtils().parse("2018-7-29 12:12:30","yyyy-MM-dd HH:mm:ss");

小黑贴了一下重写的工具类:
public enum DateUtils {
SINGLETON;
private static final Map<String, DateTimeFormatter> FORMATTER_CACHE = new HashMap<>();
public String format(LocalDateTime target, String pattern) {
return getOrCreateFormatter(pattern).format(target);
}
public LocalDateTime parse(String target, String pattern) {
return LocalDateTime.parse(target, getOrCreateFormatter(pattern));
}
private DateTimeFormatter getOrCreateFormatter(String pattern) {
DateTimeFormatter formatter;
if (FORMATTER_CACHE.containsKey(pattern)) {
formatter = FORMATTER_CACHE.get(pattern);
} else {
formatter = DateTimeFormatter.ofPattern(pattern);
FORMATTER_CACHE.put(pattern, formatter);
}
return formatter;
}
}
//调用
DateUtils.SINGLETON.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss");
LocalDateTime target = DateUtils.SINGLETON.parse("2018-7-29 12:12:30", "yyyy-MM-dd HH:mm:ss");

Doge拷贝了小黑的工具类代码,并且仿照这个类的逻辑完成了其他工具类的代码重构。
(本文完)
GOF设计模式之单例模式的更多相关文章
- GoF设计模式学习-单例模式
1.目的 控制实例的个数,类设计者应该保证只有一个实例,不能将此责任[只有一个实例]强制交给类使用者. 2.整体实现 1.单线程单例模式的实现. using System; using System. ...
- 10月27日PHP加载类、设计模式(单例模式和工厂模式)、面向对象的六大原则
加载类可以使用include.require.require_once三种中的任意一种,每个关键字都有两种方法,但是这种方法的缺点是需要加载多少个php文件,就要写多少个加载类的方法.一般也就需要加载 ...
- GOF设计模式特烦恼
这段时间,学习状态比较一般,空闲时基本都在打游戏,和研究如何打好游戏,终于通过戏命师烬制霸LOL,玩笑了.为了和"学习"之间的友谊小船不翻,决定对以往学习过的GOF设计模式做一个简 ...
- OOAD-设计模式(二)之GRASP模式与GOF设计模式概述
一.GRASP模式(通用责任分配软件模式)概述 1.1.理解责任 1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...
- GOF设计模式快速学习
这段时间,学习状态比较一般,空闲时基本都在打游戏,和研究如何打好游戏,终于通过戏命师烬制霸LOL,玩笑了.为了和"学习"之间的友谊小船不翻,决定对以往学习过的GOF设计模式做一个简 ...
- Java 设计模式之单例模式(一)
原文地址:Java 设计模式之单例模式(一) 博客地址:http://www.extlight.com 一.背景 没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴. 本篇内容为 Java ...
- python设计模式之单例模式(二)
上次我们简单了解了一下什么是单例模式,今天我们继续探究.上次的内容点这 python设计模式之单例模式(一) 上次们讨论的是GoF的单例设计模式,该模式是指:一个类有且只有一个对象.通常我们需要的是让 ...
- 漫谈 GOF 设计模式在 Spring 框架中的实现
原文地址:梁桂钊的博客 博客地址:http://blog.720ui.com 欢迎关注公众号:「服务端思维」.一群同频者,一起成长,一起精进,打破认知的局限性. 漫谈 GOF 设计模式在 Spring ...
- 设计模式之单例模式(Singleton)
设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
随机推荐
- 如何判断图中存环(正&负)
1.正环 用 SPFA不断的进行松弛操作,发现当前金额可以比本身大就更新,同时记录更新次数.如果更新次数超过n次,说明存在”正“环. 2.负环 这里先说明下负环.(求最短距离的时候) 在我们用SPFA ...
- [BZOJ1975][SDOI2010]魔法猪学院(k短路,A*)
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2748 Solved: 883[Submit][Statu ...
- 8VC Venture Cup 2016 - Elimination Round G. Raffles 线段树
G. Raffles 题目连接: http://www.codeforces.com/contest/626/problem/G Description Johnny is at a carnival ...
- httpWebRequest 文件下载
服务版本: go file system ssdb github: https://github.com/dtxlink/gfs 上一篇: 一个 go 文件服务器 ssdb 通过 httpWebReq ...
- HDU 3537 Daizhenyang's Coin(博弈,翻硬币)
Daizhenyang's Coin Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- TWinHTTP
TWinHTTP USES SynCrtSock procedure hget(const url: string; var ResponseCode: Integer; var ResponseHe ...
- 虚函数&纯虚函数&抽象类&虚继承
C++ 虚函数&纯虚函数&抽象类&接口&虚基类 1. 多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过 ...
- JBoss入门
很多内容摘自 https://www.jianshu.com/p/4baaf549436b 1.安装目录 安装完Jboss后得目录结构 目录 功能 appclient/ 包含应用程序客户容器的配置细节 ...
- python部署工具fabric
两台机器:10.1.6.186.10.1.6.159.fabric部署在10.1.6.186上面 1 执行和1相同的任务,不过排除掉10.1.6.159这台机器 1 #!/usr/bin/pytho ...
- select标签中option内容加链接
1.Html页面代码 <select name="select" id="select" style="height: 25px; width: ...