英文原文: https://sourcemaking.com/design_patterns/singleton

意图

  • 确保一个类只有一个实例,并提供一个访问其实例的全局点;
  • 封装 “即时初始化” (just-in-time initialization)或 “首次使用时初始化” (initialization on first use)。

问题

应用需要一个且唯一一个对象的实例。而且,延迟初始化(lazy initialization)和全局访问是必须的。

讨论

使得具有单一实例对象的类负责创建、初始化、访问和执行。声明这个实例作为一个私有静态数据成员。提供一个公共静态成员函数封装所有的初始化代码,同时提供对这个实例的访问。

任何时候,需要引用单一实例时,客户端(使用类名和范围精度操作符1)调用 accessor 函数。

只有满足所有下面三个标准时,才应该考虑单例模式:

  • 单个实例的所有权不能合理分配;
  • 延迟初始化是可取的;
  • 全局访问未另行规定;

如果单个成员实例的所有权,何时以及如何初始化,全局访问都不是问题,那么单例模式将不足以令人感兴趣。

单例模式可以扩展到支持访问包含大量实例的具体应用。

“静态成员函数访问器”(static member function accessor)方法将不会支持 Singleton类的子类。如果需要子类,参考本书中的讨论。

删除一个Singleton类/实例是一个有意义的设计问题。可查看John Vlissides在讨论中所说 "To Kill A Singleton" 。

结构

使得包含单一实例的类负责访问和在第一次使用时初始化。这个单一实例是一个私有静态属性。而 accessor 函数是一个公共静态方法。

示例

Singleton 模式确保这种类只有一个实例,并提供此实例的全局访问点。它根据 singleton set 命名,singleton set 定义了一个只包含一个元素的集合。美国总统办公室就是一个单例。美国宪法指定总统的选举方式,限制了其任期,并定义了继任的顺序。所以,在任何给定时间,最多只有一个有效的总统。不管这个有效的总统的个人身份,这个标题 “美国总统” 是一个全局访问点,识别在办公室的那个人。

清单

  1. 在 “单一实例” 类中,定义一个私有静态属性。
  2. 在这个类中,定义一个公有静态 accessor 函数。
  3. 在访问器(accessor)函数中,进行 “延迟初始化”(在首次使用时创建)。
  4. 定义所有构造体为 protected 或 private 。
  5. 客户端可能只能使用 accessor 函数来操控 Singleton 。

经验法则

  • Abstract Factory,Builder 和  Prototype  可以在它们实现中使用 Singleton 。
  • Facade 对象常常是 Singletons,因为其只需要唯一一个 Facade 对象。
  • 状态对象常常是 Singletons 。
  • Singleton 对于全局变量的优势是当你使用 Singleton 时,你绝对确信实例的数目,而且你可以改变你的思维和管理任何数量的实例。
  • Singleton 设计模式是最多被不恰当使用的模式之一。Singletons 只有在一个类必须只有一个实例,不能多,也不能少时,才能确定使用。设计者经常错误地使用 Singletons 替代全局变量。Singleton 出于意图和目的是一个全局变量。Singleton 并没有消除全局变量,它只是对其重命名。
  • 什么时候 Singleton 是不必要的?简短的答案:大多数时候。长答案:当以引用的方式传递一个对象资源给需要它的对象更容易的时候,而不是让对象全局访问资源。对于 Singletons,真正的问题是它们给你一个好借口,不要仔细考虑一个对象的合适的可见性。发现在公开和保护对象之间合适的平衡,对于维护灵活性是非常重要的。

因为我们组有使用全局变量的坏习惯,所以我组织了关于 Singleton 的学习小组。接下来,我发现 Singletons 到处出现,而与全局变量相关的问题一个都没有消失。对全局数据的问题的答案并不是把它变成 Singleton 。其答案是 “到底你们为什么使用全局变量?” 改变名字不能改变问题。实际上,这样,可能会使情况变坏,因为你有机会说,“哦,我没有那样做,我是这样做的” —— 即使这样和那样是同一个事情。

代码示例

Java Singleton in Java Singleton in Java
C++ Singleton in C++: Before and after Singleton in C++
PHP Singleton in PHP
Delphi Singleton in Delphi
Python Singleton in Python

译者注:

1、范围精度操作符 - scope resolution operator,即 "::"

[翻译] 单例(Singleton)的更多相关文章

  1. 跨应用程序域(AppDomain)的单例(Singleton)实现

    转载自: 跨应用程序域(AppDomain)的单例(Singleton)实现 - CorePlex代码库 - CorePlex官方网站,Visual Studio插件,代码大全,代码仓库,代码整理,分 ...

  2. OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式

    在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...

  3. spring mvc 的Controller类默认Scope是单例(singleton)的

    使用Spring MVC有一段时间了,之前一直使用Struts2,在struts2中action都是原型(prototype)的, 说是因为线程安全问题,对于Spring MVC中bean默认都是(s ...

  4. 【Java学习笔记之三十】详解Java单例(Singleton)模式

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  5. 瞎扯设计模式1:单例模式 饿汉模式 懒汉模式 线程安全的单例 singleton 设计模式 java

    [原创声明]此文为本人原创,欢迎转载,转载请注明出处,作者链接~ http://www.cnblogs.com/m-yb/p/8833085.html 单例很常用,面试也经常被问,如:不用自定义锁怎么 ...

  6. JAVA中实现单例(Singleton)模式的八种方式

    单例模式 单例模式,是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例.即一个类只有一个对象实例. 基本的实现思路 单 ...

  7. Lumen开发:lumen源码解读之初始化(3)——单例(singleton)与中间件(Middleware)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 今天来讲讲Lumen的singleton和Middleware,先来看看起始文件bootstrap/app.php / * | --------- ...

  8. 单例Singleton

    先提供一个完整版: // .h文件 @interface SingleTon : NSObject /** 获取单例对象 */ + (instancetype)sharedInstance; + (i ...

  9. 设计一个线程安全的单例(Singleton)模式

    在设计单例模式的时候.尽管非常easy设计出符合单例模式原则的类类型,可是考虑到垃圾回收机制以及线程安全性.须要我们思考的很多其它.有些设计尽管能够勉强满足项目要求,可是在进行多线程设计的时候.不考虑 ...

随机推荐

  1. 论文阅读 | CenterNet:Object Detection with Keypoint Triplets

    相关链接 论文地址:https://arxiv.org/abs/1904.08189 代码链接:https://github.com/Duankaiwen/CenterNet 概述 CenterNet ...

  2. git提交代码

    安装 Windows 下载安装地址 Linux 1 yum install git / apt-get install git 安装后执行,正常显示则安装正常 1 git --version 使用 生 ...

  3. 实现接口必须要加注解@Override吗

    不一定的,但是我们的编译器在查询我们重写的方法,方法名,参数,返回类型的时候,是能够根据注解来帮助我们判断方法重写的正确与否 所以我们有必要在编写过程中加上@Override,虽然我们的eclipse ...

  4. Python学习 day13

    一.可迭代对象和迭代器 1.回顾可以被for循环的对象 list.dic.str.set.tuple.文件句柄f.range().enumerate() 只有可迭代对象才能被for循环,当我们遇到一个 ...

  5. 快手、抖音、微视类短视频SDK接入教程,7步就能搞定

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由视频咖 发表于云+社区专栏 终端部分 按照如下三步操作,可以用 XCode 或者 Android Studio 编译和调试小视频 Ap ...

  6. ajax传json

    需求 前台有许多字段需要用ajax传送给后台, 如果给直接将字段封装成JSON对象传给后台会很方便 解决 ajax 发送 var str = {"name":"xiaom ...

  7. 互联网轻量级框架SSM-查缺补漏第九天

    简言: 第九章 Spring Ioc的概念 IoC(Inversion of Control)控制反转:比如想喝橙汁,在没有饮品店的日子,最直观的做法是买果汁机.橙汁.这是你自己“主动”创造的过程,也 ...

  8. log4j的简单使用

    引入jar包org.apache.log4j.Logger,项目src目录下建立一个log4j.properties配置文件 log4j.rootLogger=INFO,A1,R log4j.appe ...

  9. Spring课程 Spring入门篇 6-3 ProxyFactoryBean及相关内容(下)

    1 解析 1.1 使用global advisors demo 1.2 jdk代理和cglib代理的选择 1.3 如何强制使用CGLIB实现AOP? 1.4 JDK动态代理和CGLIB字节码生成的区别 ...

  10. 纪念一个神坑——react-native-echarts

    一.问题 在rn项目里引用的时候,本该显示图表的界面显示出了一堆html... 二.原因 官方没给配置好 三.解决 1./node_modules/native-echarts/src/compone ...