单例模式(中):单例模式的弊端
- 单例对 OOP 特性的支持不友好
public class Order {
public void create(...) {//...long id = IdGenerator.getInstance().getId(); //... } } public class User { public void create(...) { // ...long id = IdGenerator.getInstance().getId(); //... } }
IdGenerator 的使用方式违背了基于接口而非实现的设计原则,也就违背了广义上理解的 OOP 的抽象特性。
单例类也可以被继承、也可以实现多态,只是 实现起来会非常奇怪,会导致代码的可读性变差。
单例会隐藏类之间的依赖关系
单例类不需要显示创建、不需要依赖参数传递,在函数中直接调用 就可以了。如果代码比较复杂,这种调用关系就会非常隐蔽。单例对代码的扩展性不友好
如果我们将数据库连接池设计成单例类,显然就无法适应这样的需求变更,也就是说,单例 类在某些情况下会影响代码的扩展性、灵活性。单例对代码的可测试性不友好
如果单例类依赖比较重的外部资源,比如 DB, 我们在写单元测试的时候,希望能通过 mock 的方式将它替换掉。而单例类这种硬编码式 的使用方式,导致无法实现 mock 替换。单例不支持有参数的构造函数
如我们创建一个连接池的单例对象,我们没法通过参数来 指定连接池的大小。
第一种解决思路是:
创建完实例之后,再调用 init() 函数传递参数。需要注意的是,我们在使用这个单例类的时候,要先调用 init() 方法,然后才能调用 getInstance() 方法,否则代码会抛出异常。
具体的代码实现如下所示:
public class Singleton { private static Singleton instance = null; private final int paramA; private final int paramB; private Singleton(int paramA, int paramB) { this.paramA = paramA; this.paramB = paramB; } public static Singleton getInstance() { if (instance == null) { throw new RuntimeException("Run init() first."); } return instance; } public synchronized static Singleton init(int paramA, int paramB) { if (instance != null){ throw new RuntimeException("Singleton has been created!"); } instance = new Singleton(paramA, paramB); return instance; } } Singleton.init(10, 50); // 先init,再使用 Singleton singleton = Singleton.getInstance();
第二种解决思路是:
将参数放到 getIntance() 方法中。
具体的代码实现如下所示:
public class Singleton { private static Singleton instance = null; private final int paramA; private final int paramB; private Singleton(int paramA, int paramB) { this.paramA = paramA; this.paramB = paramB; } public synchronized static Singleton getInstance(int paramA, int paramB) { if (instance == null) {instance = new Singleton(paramA, paramB); } return instance; } }
Singleton singleton = Singleton.getInstance(10, 50);
第三种解决思路是:
将参数放到另外一个全局变量中。具体的代码实现如下。Config 是一 个存储了 paramA 和 paramB 值的全局变量。里面的值既可以像下面的代码那样通过静态 常量来定义,也可以从配置文件中加载得到。
public class Config { public static final int PARAM_A = 123; public static fianl int PARAM_B = 245;
}
public class Singleton { private static Singleton instance = null; private final int paramA; private final int paramB; private Singleton() { this.paramA = Config.PARAM_A; this.paramB = Config.PARAM_B;
}
public synchronized static Singleton getInstance() { if (instance == null) { instance = new Singleton(); }return instance; }
}
保证全局唯一,除了使用单例,我们还可以用静态方法来实现。
// 静态方法实现方式
`public class IdGenerator { private static AtomicLong id = new AtomicLong(0); public static long getId() { return id.incrementAndGet(); }
}`
// 使用举例 long id = IdGenerator.getId();
实际上,它比单例更加不 灵活,比如,它无法支持延迟加载。
另一种方法:
// 1. 老的使用方式
public demofunction() { //... long id = IdGenerator.getInstance().getId(); //... }
// 2. 新的使用方式:依赖注入
`public demofunction(IdGenerator idGenerator) { long id = idGenerator.getId();}`
// 外部调用demofunction()的时候,传入idGenerator IdGenerator idGenerator = IdGenerator.getInsance(); demofunction(idGenerator);
单例模式(中):单例模式的弊端相关推荐
- PHP中单例模式:三私一公是什么?
PHP中单例模式:三私一公是什么? 三私一公 私有化静态属性 私有化构造方法 私有化克隆方法 公有化静态方法 转载于:https://www.cnblogs.com/phpisfirst/p ...
- rethat安装MySQL多例_Spring框架-Bean作用域中单例模式和多例模式的区别
Spring框架-Bean作用域中单例模式和多例模式的区别 一.单例模式的特点(当没有指定是单例模式还是多例模式的时候,默认是单例模式): 1.Spring容器创建的时候,对应的类的实例化对象一起被创 ...
- 线程的同步之Synchronized在单例模式中的应用
synchronized在单例模式中的使用 在单例模式中有一种懒汉式的单例,就是类初始化的时候不创建对象.等第一次获取的时候再创建对象.这种单例在单线程下是没有问题的获取的也都是同一个对象.但是如果放 ...
- Python单例模式中几种实现及优化方法
单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...
- python实现单例模式的几种方式_基于Python中单例模式的几种实现方式及优化详解...
单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...
- Spring Boot 单例模式中依赖注入问题
在日常项目开发中,单例模式可以说是最常用到的设计模式,项目也常常在单例模式中需要使用 Service 逻辑层的方法来实现某些功能.通常可能会使用 @Resource 或者 @Autowired 来自动 ...
- Java双重检查懒汉式单例模式中volatile的作用
先看下懒汉式单例模式双重检查的写法 public class Lazy2 {private volatile static Lazy2 instance;private Lazy2 (){}publi ...
- 为什么单例模式中的Double Check要加volatile
对于单例模式的详细内容,请参考我的上一篇文章 https://blog.csdn.net/Jarvenman/article/details/100136562 在单例模式中,有一种写法叫Double ...
- Java单例模式中的线程安全问题
在Java中单例模式被分为懒汉式和饿汉式,饿汉式会在单例类加载时就创建实例而懒汉式则延迟实例化,在使用到单例实例的时候才实例化.在单线程的程序里两张方式没什么区别,多线程的话懒汉式会有线程安全问题.先 ...
- C#中单例模式的实现
文章目录 一.引言 二.单例模式 1. 单例模式 1.1. 场景 1.2. 问题产生 1.3. 应当考虑的 1.4. 解决方案 2. C#中实现单例模式 2.1. 场景 2.2. 实现策略 2.2.1 ...
最新文章
- redis-sentinel 主从复制高可用
- sublime text常用快捷键
- js实现图片无缝连接
- 关于路径搜索的算法, 可能用到
- 《Photoshop修色圣典(第5版)》目录—导读
- ASP.NET MVC3 上传头像图片并截图
- C++ 重载机制实现原理
- java 常量池详解
- [C++]MySQL数据库操作实例
- QImage QPixmap Mat区别
- spring 优越性实践
- ftp导入oracle,ftp向linux虚拟机传oracle安装包
- 计算机二级C语言程序设计 第一章 程序设计基本概念
- Sigmoid函数总结
- RecyclerView使用中遇到的问题
- 计算机组装与维修标准教程,计算机组装与维护标准教程(2008版)
- 频谱分析中的频谱泄露现象(以ADC性能测试场景为例)
- [ffmpeg][goav]ffmpeg代码例子pcmu重采样并转码aac格式
- nagios的原理及server端跟client端安装配置全部过程
- 如何从零构建对内网穿透的理解
热门文章
- Jenkins+Jmeter+Gitlab+Ant接口自动化持续集成构建(环境搭建配置)
- 算法竞赛入门经典+挑战编程+USACO
- Verilog HDL高级数字设计 从零学习(一)
- 【CodeForce】559B Equivalent Strings 等效字符串
- 通过命令行运行matlab代码
- 1.2 聪明的投资者:投资与投机(聪明投资者的预期收益)
- CRMED知识付费2.0源码 已去授权
- 表示表元的背景的html,表示表元的背景色彩的HTML 是()
- Windows 10 Enterprise LTSB版本
- 多功能计算机十二生肖,十二生肖那是真人实演的危险特技,不是电脑特效!