1. 单例对 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 的抽象特性。

单例类也可以被继承、也可以实现多态,只是 实现起来会非常奇怪,会导致代码的可读性变差。

  1. 单例会隐藏类之间的依赖关系
    单例类不需要显示创建、不需要依赖参数传递,在函数中直接调用 就可以了。如果代码比较复杂,这种调用关系就会非常隐蔽。

  2. 单例对代码的扩展性不友好
    如果我们将数据库连接池设计成单例类,显然就无法适应这样的需求变更,也就是说,单例 类在某些情况下会影响代码的扩展性、灵活性。

  3. 单例对代码的可测试性不友好
    如果单例类依赖比较重的外部资源,比如 DB, 我们在写单元测试的时候,希望能通过 mock 的方式将它替换掉。而单例类这种硬编码式 的使用方式,导致无法实现 mock 替换。

  4. 单例不支持有参数的构造函数
    如我们创建一个连接池的单例对象,我们没法通过参数来 指定连接池的大小。
    第一种解决思路是:
    创建完实例之后,再调用 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);

单例模式(中):单例模式的弊端相关推荐

  1. PHP中单例模式:三私一公是什么?

    PHP中单例模式:三私一公是什么? 三私一公 私有化静态属性 私有化构造方法 私有化克隆方法 公有化静态方法 ​​​​ 转载于:https://www.cnblogs.com/phpisfirst/p ...

  2. rethat安装MySQL多例_Spring框架-Bean作用域中单例模式和多例模式的区别

    Spring框架-Bean作用域中单例模式和多例模式的区别 一.单例模式的特点(当没有指定是单例模式还是多例模式的时候,默认是单例模式): 1.Spring容器创建的时候,对应的类的实例化对象一起被创 ...

  3. 线程的同步之Synchronized在单例模式中的应用

    synchronized在单例模式中的使用 在单例模式中有一种懒汉式的单例,就是类初始化的时候不创建对象.等第一次获取的时候再创建对象.这种单例在单线程下是没有问题的获取的也都是同一个对象.但是如果放 ...

  4. Python单例模式中几种实现及优化方法

    单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...

  5. python实现单例模式的几种方式_基于Python中单例模式的几种实现方式及优化详解...

    单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...

  6. Spring Boot 单例模式中依赖注入问题

    在日常项目开发中,单例模式可以说是最常用到的设计模式,项目也常常在单例模式中需要使用 Service 逻辑层的方法来实现某些功能.通常可能会使用 @Resource 或者 @Autowired 来自动 ...

  7. Java双重检查懒汉式单例模式中volatile的作用

    先看下懒汉式单例模式双重检查的写法 public class Lazy2 {private volatile static Lazy2 instance;private Lazy2 (){}publi ...

  8. 为什么单例模式中的Double Check要加volatile

    对于单例模式的详细内容,请参考我的上一篇文章 https://blog.csdn.net/Jarvenman/article/details/100136562 在单例模式中,有一种写法叫Double ...

  9. Java单例模式中的线程安全问题

    在Java中单例模式被分为懒汉式和饿汉式,饿汉式会在单例类加载时就创建实例而懒汉式则延迟实例化,在使用到单例实例的时候才实例化.在单线程的程序里两张方式没什么区别,多线程的话懒汉式会有线程安全问题.先 ...

  10. C#中单例模式的实现

    文章目录 一.引言 二.单例模式 1. 单例模式 1.1. 场景 1.2. 问题产生 1.3. 应当考虑的 1.4. 解决方案 2. C#中实现单例模式 2.1. 场景 2.2. 实现策略 2.2.1 ...

最新文章

  1. redis-sentinel 主从复制高可用
  2. sublime text常用快捷键
  3. js实现图片无缝连接
  4. 关于路径搜索的算法, 可能用到
  5. 《Photoshop修色圣典(第5版)》目录—导读
  6. ASP.NET MVC3 上传头像图片并截图
  7. C++ 重载机制实现原理
  8. java 常量池详解
  9. [C++]MySQL数据库操作实例
  10. QImage QPixmap Mat区别
  11. spring 优越性实践
  12. ftp导入oracle,ftp向linux虚拟机传oracle安装包
  13. 计算机二级C语言程序设计 第一章 程序设计基本概念
  14. Sigmoid函数总结
  15. RecyclerView使用中遇到的问题
  16. 计算机组装与维修标准教程,计算机组装与维护标准教程(2008版)
  17. 频谱分析中的频谱泄露现象(以ADC性能测试场景为例)
  18. [ffmpeg][goav]ffmpeg代码例子pcmu重采样并转码aac格式
  19. nagios的原理及server端跟client端安装配置全部过程
  20. 如何从零构建对内网穿透的理解

热门文章

  1. Jenkins+Jmeter+Gitlab+Ant接口自动化持续集成构建(环境搭建配置)
  2. 算法竞赛入门经典+挑战编程+USACO
  3. Verilog HDL高级数字设计 从零学习(一)
  4. 【CodeForce】559B Equivalent Strings 等效字符串
  5. 通过命令行运行matlab代码
  6. 1.2 聪明的投资者:投资与投机(聪明投资者的预期收益)
  7. CRMED知识付费2.0源码 已去授权
  8. 表示表元的背景的html,表示表元的背景色彩的HTML 是()
  9. Windows 10 Enterprise LTSB版本
  10. 多功能计算机十二生肖,十二生肖那是真人实演的危险特技,不是电脑特效!