慎用单例模式!

   一年前曾经非常开心的修改了QQ签名,“酷爱单例模式”!

     经典设计模式书的第一讲,这是个如此神奇的模式,比C里的全局变量看起来更有过之而无不及,在任何地方,只要引用了库名称,你就能获得全局访问点,随时修改随时读取,岂不爽哉?

     于是,在一段时间内,我把我非常重要的几个实体类都用单例模式实现了,任何地方都可访问,解决了好多大难题!

     但,越到后来,越隐隐约约的发现,单例是个笑面杀手!

 

     对程序架构而言,单例意味着没有隐藏,插入到程序的任何组件都可以随时修改它,这客观上违背了面向对象的最小公开法则,程序健壮性安全性骤降。

     对程序扩展性而言,单例意味着很难被继承重写!  当你在一个单例中尝试覆盖它的某些功能时,编译器会报错,这时候你哭去吧。或者,你会奇怪的发现,咦?怎么还是基类的功能!

     对程序逻辑而言,单例,顾名思义,仅有其一,但你的程序在发展着,你确定只有一个实例即可?某天突然发现,业务变了,需要扩展,那些数不清的用单例调用的代码怎么处理?尤其是已经发布到顾客手中的代码?

     对效率而言,每次访问它的时候,都会查看是否被创建(多增加了一次判断),这对于一些需要高性能的程序是非常不合适的。

     对多线程而言,在多线程环境下,实现单例是需要技巧的。否则,单例不单!

     对对象生命周期而言,单例只有自己持有真正的引用,,如何销毁何时销毁都是问题,可能还会造成指针悬挂。

     对开发者而言,一个类不能new! 这还会带来更多的疑问和混淆。

 

     于是,我便站在了这样的十字路口,要么花大力气重写核心代码,要不延续单例模式的老路,再痛苦几年。

     痛定思痛, 我决定改掉那个模式。 大概,单例是个真正需求较窄的设计模式,仅仅适合设计配置参数上管理类,或者调试输出类(大家司空见惯的Log),或者是一些全局访问但功能相对单一的功能,千万别尝试将单例包装到复杂的数据实体上,这样做只是饮鸩止渴,哪天回过头来,就像操作系统的注册表一样,又臭又长,带来的危险比带来的好处还多得多!

     有一期“程序员”杂志刊登了一篇采访 GoF(设计模式作者)的文章,他们计划对<设计模式>进行修订,其中还特别提到要剔除“单例模式”,认为单例模式很容易在系统中产生“代码的臭味”,期待新版的设计模式早点出来。

     共勉。

时间: 2024-10-26 00:19:02

慎用单例模式!的相关文章

scala实现单例模式

单例模式介绍 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. 对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务:一个系统只能有一个窗口管理器或文件系统:一个系统只能有一个计时工具或ID(序号)生成器.如在Windows中就只能打开一个任务管理器.如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源:

io-dom4j中因为输出流未正确关闭,导致再次获取单例模式的document时,对象为null

问题描述 dom4j中因为输出流未正确关闭,导致再次获取单例模式的document时,对象为null 一:如下是获取单例模式的document对象. private static Document returndoc(Document docuname, String xmlname) { if (docuname != null) { return docuname; } SAXReader reader = new SAXReader(); // 如果不存在就创建对象. try { docu

[设计模式实践之路](1)单例模式

[简介] 单例模式(Singleton)保证一个类仅有一个实例,并提供一个访问它的全局访问点.      实现单例模式的一个最好的方法就是让类自身负责保存它的唯一实例.这个类可以保证没有其他实例可以创建,并且它可以提供一个访问该实例的方法. [特点] 单例模式具有一下特点: 单例类只有一个实例 单例类必须自己创建自己的唯一实例 单例类必须给所有其他对象提供这一实例 [分类] 主要的就是懒汉单例,饿汉单例 [懒汉单例] package Mode; /** * Java设计模式之单例模式 * @au

C# 单例模式的五种写法

C# 单例模式的五种写法及优劣分析,见下文: [单例模式及常见写法](http://blog.csdn.net/jiankunking/article/details/50867050)

如何正确地写出单例模式

单例模式算是设计模式中最容易理解,也是最容易手写代码的模式了吧.但是其中的坑却不少,所以也常作为面试题来考.本文主要对几种单例写法的整理,并分析其优缺点.很多都是一些老生常谈的问题,但如果你不知道如何创建一个线程安全的单例,不知道什么是双检锁,那这篇文章可能会帮助到你. 懒汉式,线程不安全 当被问到要实现一个单例模式时,很多人的第一反应是写出如下的代码,包括教科书上也是这样教我们的. public class Singleton { private static Singleton instan

减小内存的占用问题——享元模式和单例模式的对比分析

俗话说,自己写的代码,6个月后也是别人的代码--复习!复习!复习!总结的知识点如下: 享元模式概念和实现例子 使用了享元模式的Java API String类 java.lang.Integer 的 valueOf(int)方法源码分析 使用享元模式的条件 享元模式和单例模式的区别 前面的策略模式的话题提起了:如何解决策略类膨胀的问题,说到 "有时候可以通过把依赖于环境Context类的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用."换言之,可以使

PHP单例模式实现商城购物车功能-PHP实例教程

  PHP单例模式实现商城购物车功能-PHP实例教程完成这个小功能必须会写需求 养成好的习惯 Php购物车的开发需求功能如下 1: 购物车放在session里 2: 单例模式来开发 功能: 增删改查 增一个商品 减少 PHP单例模式实现商城购物车功能-PHP实例教程完成这个小功能必须会写需求 养成好的习惯 Php购物车的开发需求功能如下:php100.com 1: 购物车放在session里 2: 单例模式来开发 功能: 增删改查 增一个商品 减少一个商品(改,数量) 删 去掉一个商品 清空购物

php设计模式之单例模式(单元素模式)

单例模式: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例.它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用. (1). 需要一个保存类的唯一实例的静态成员变量:private static $_instance; (2). 构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义: private function __construct() { $this->_db = pg_connect('xxxx')

PHP的单例模式的一个实例

这篇文章对于PHP单例模式的解释并不一定完善!只是举一个实例而已,目的是让我自己通过一个实例可以加深对单例模式的理解!在此,仅供参考! 单例:可以简单的理解是通过一个类,只能实例化单个对象,不能实例化多个对象! class e { public $uname; static $obj = NULL; //定义一个静态属性 private function __construct() { //在构造方法前使用private属性,目的是不能在类的外部实例化对象, //即不能$a=new e(); }