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) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
随机推荐
- POJ 1182 食物链 【带权并查集/补集法】
动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种.有人用两种说 ...
- ANY和SOME 运算符
在SQL中ANY和SOME是同义词,所以下面介绍的时候只使用ANY,SOME的用法和功能和ANY一模一样.和IN运算符不同,ANY必须和其他的比较运算符共同使用,而且必须将比较运算符放在ANY 关键字 ...
- 2017icpc 乌鲁木齐网络赛
A .Banana Bananas are the favoured food of monkeys. In the forest, there is a Banana Company that pr ...
- BZOJ 2225 [Spoj 2371]Another Longest Increasing(CDQ分治)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2225 [题目大意] 给定N个数对(xi,yi),求最长上升子序列的长度. 上升序列定义 ...
- (原创)Stanford Machine Learning (by Andrew NG) --- (week 8) Clustering & Dimensionality Reduction
本周主要介绍了聚类算法和特征降维方法,聚类算法包括K-means的相关概念.优化目标.聚类中心等内容:特征降维包括降维的缘由.算法描述.压缩重建等内容.coursera上面Andrew NG的Mach ...
- 消除重复 Exercise07_15
import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:消除重复 */ public class Exercise07_15 { ...
- Ubuntu 16.04通过NetworkManager(GUI)配置网桥
说明:配置好网桥之后一定要重启,不然不生效.这个是Desktop版GUI设置的问题.Server版不会. 配置: 参考: http://www.jb51.net/LINUXjishu/333778.h ...
- CString.Format %s 字符串 要用char *
CString.Format %s 字符串 错了,应该是:std::string str;CString sql;sql.Format("%s",str.c_str());所以正确 ...
- jQuery.extend重载合并
使用: var people1 = { apple: 0, banana: { weight: 52, price: 100 }, age: 97 }; var people2 = { banana: ...
- 在 Ubuntu 14.04 上安装 Ubuntu Tweak 0.8.8
转自:http://linux.cn/article-3335-1.html 关于 Ubuntu Tweak,Ubuntu 老用户再熟悉不过了,Ubuntu tweak 相当于 windows 的优化 ...