Design Pattern —— Singleton

Design Pattern —— Singleton   强力推荐枚举和类级内部类方式实现单例模式

单例模式是开发中非常常用的一种模式,简单的说,我们希望一个类永远都只有一个对象。

主要有两个用途:

1.存储一些进程内共享的值(不是很推荐,大部分情况下还是应该用局部变量,互相传递值的方式)

2.任何时候都不变的操作

单例模式的实现目前已知的有五种:

1.饿汉式

2.懒汉式

3.双重验证

4.类级内部类

5.枚举

一、饿汉式

类加载时就创建好对象,以空间换时间。这样外部调用EagerSingleton.getInstance()时,直接获得这个创建好的对象。

 1 public class EagerSingleton {
 2     private static EagerSingleton instance = new EagerSingleton();
 3     /**
 4      * 私有默认构造子
 5      */
 6     private EagerSingleton(){}
 7     /**
 8      * 静态工厂方法
 9      */
10     public static EagerSingleton getInstance(){
11         return instance;
12     }
13 }

优点:节省运行时间

缺点:占用空间

二、懒汉式

类加装时不创建对象,直到需要使用时才创建。

 1 public class LazySingleton {
 2     private static LazySingleton instance = null;
 3     /**
 4      * 私有默认构造子
 5      */
 6     private LazySingleton(){}
 7     /**
 8      * 静态工厂方法
 9      */
10     public static synchronized LazySingleton getInstance(){
11         if(instance == null){
12             instance = new LazySingleton();
13         }
14         return instance;
15     }
16 }

优点:节省空间,如果一直不用,就不会创建

缺点:每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。且是由于是线程安全的,所以会降低整体的访问速度

三、双重验证

双重验证的单例模式,是懒汉式单例的一种优化方式。既实现线程安全,又能够使性能不受很大的影响。

定义:

1.先不同步,进入方法后,先检查实例是否存在,如果不存在才进行下面的同步块,这是第一重检查;

2.进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。

这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

  “双重检查加锁”机制的实现会使用关键字volatile,简单的说:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

 1 public class Singleton {
 2     private volatile static Singleton instance = null;
 3     private Singleton(){}
 4     public static Singleton getInstance(){
 5         //先检查实例是否存在,如果不存在才进入下面的同步块
 6         if(instance == null){
 7             //同步块,线程安全的创建实例
 8             synchronized (Singleton.class) {
 9                 //再次检查实例是否存在,如果不存在才真正的创建实例
10                 if(instance == null){
11                     instance = new Singleton();
12                 }
13             }
14         }
15         return instance;
16     }
17 }

双重验证的方式虽然看上去很美,但是是不被推荐使用的。具体volatile的使用也是一个比较大的课题,有一篇非常好的文章推荐http://www.cnblogs.com/dolphin0520/p/3920373.html

四、类级内部类实现的方式。

那我们能不能想到一个办法,既让第一次使用时才创建对象,又解决线程安全呢。

类级内部类的特点:

1.类级内部类的对象和外部类对象没有依赖关系

2.类级内部类中可以有静态方法,此静态方法只能调用外部类的静态方法和成员变量

3.类级内部类只有在第一次使用时才会加载

JVM在有些时候会隐式的去执行同步操作:

1.由静态初始化器(在静态字段上或static{}块中的初始化器)初始化数据时

2.访问final字段时

3.在创建线程之前创建对象时

4.线程可以看见它将要处理的对象时

实现线程安全:可以采用静态初始化器的方式,它可以由JVM来保证线程的安全性。

实现延迟加载:采用类级内部类,在这个类级内部类里面去创建对象实例。只要不使用到这个类级内部类,那就不会创建对象实例。

 1 public class Singleton {
 2
 3     private Singleton(){}
 4     /**
 5      *    类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
 6      *    没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
 7      */
 8     private static class SingletonHolder{
 9         /**
10          * 静态初始化器,由JVM来保证线程安全
11          */
12         private static Singleton instance = new Singleton();
13     }
14
15     public static Singleton getInstance(){
16         return SingletonHolder.instance;
17     }
18 }

五、枚举实现单例

《effectJava》一书中重点推荐的实现单例的方式

 1 public enum Singleton {
 2     /**
 3      * 定义一个枚举的元素,它就代表了Singleton的一个实例。
 4      */
 5
 6     uniqueInstance;
 7
 8     /**
 9      * 单例可以有自己的操作
10      */
11     public void singletonOperation(){
12         //功能处理
13     }
14 }

枚举单例,简洁,提供序列化机制,防止多实例化,防止反射,是实现单例的最佳方案。

参考资料

http://www.cnblogs.com/dolphin0520/p/3920373.html  violate详解

http://www.cnblogs.com/java-my-life/archive/2012/03/31/2425631.html  java与模式之单例模式

《effectJava》

时间: 2025-01-07 16:21:02

Design Pattern —— Singleton的相关文章

Design Pattern Singleton 单一模式

单一模式的几个注意点: 一) 设计单一模式,首先需要把构造函数给私有化了,不让外界访问,那么外界只能通过提供的函数获取一个新的类. 二) C++的单一模式,记得要在类外初始化一个类,否则或内存出错的. 三) 这个唯一的类必须是要静态的 程序: #ifndef _SINGLETON_H #define _SINGLETON_H #include <iostream> #include <string> using namespace std; class DuGuJiuJian {

[Design Pattern] Singleton Pattern 简单案例

Singleton Pattern, 即单例模式,用于获取类的一个对象,该对象在整个应用中是其类的唯一对象.单例模式属于创建类的设计模式. SingleObject 作为单例类,内含了一个静态私有的 SingleObject 成员变量,将构造方法私有化使得外部无法构造 SingleObject 的对象,同时提供一个公共的 getInstance 方法,提供唯一的对象. 代码实现: 单例类 SingleObject public class SingleObject { private stati

Design Pattern - Singleton

单例模式 定义:确保一个类只有一个实例,并提供一个全局访问点. 设计思路 私有化构造函数,使外界不能创建该类的实例 对外开放一个共有静态方法,用于并返回全局唯一实例. 示例代码(C#) /// <summary> /// 单例模式的实现 /// </summary> public class Singleton { private static Singleton m_Singleton; private static readonly object locker = new ob

Head First Design Pattern 读书笔记(4) 单例模式

Head First Design Pattern 读书笔记(4) Singleton Pattern 单例模式 Silngleton Pattern 类图 单例模式非常简单,基本没有什么类之间的关系,就不画图了,保证某个类生成的实例只有一个即可. 定义 单例模式:只允许一个类实例化一个对象,并提供一个可以全局访问这个实例的方法(接口). 关于单例模式 最简单的单例模式实现方法是: /* *"懒汉式"写法,即等要用了再去实例化实例对象,而不是应用一启动就实例化好放在容器中. */ pu

C++ Design Pattern: What is a Design Pattern?

Q: What is a Design Pattern? A: Design Patterns represent solutions to problems what arise when developing software within a particular context. Each pattern describes a problem which occurs over and over again in our environment, and then describes

设计模式(Design pattern)概述

设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结, 使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性 设计框架 可复用面向对象软件系统一般划分为两大类:应用程序工具箱和框架(Framework) 我们平时开发的具体软件都是应用程序 而框架是构成一类特定软件可复用设计的一组相互协作的类 框架通常定义了应用体系的整体结构类和对象的关系等等设计参数,以便于具体应用实现者能集中精力于应用本身的特定细节. 框架主要记录软件应用中

Null Object Design Pattern (Python recipe)

Null Object 个人感觉非常有用.也是在review公司其他同事写代码的时候看到. 当时使用了flask的request全局请求变量g,然后使用了g.x保存了一个东西. 当时在view代码读取g.x的时候震惊了,因为这一段代码并没有保存g.x,按道理来说应该是一个空值,当我拿着空值去调用其属性的时候应该会报AttributeError. 但是什么也没有发生,既没有报错,也没有发生什么,而且对其判断还是False,于是查看其实现才发现了这个.以下全部转自http://code.active

DP什么意思 design pattern 设计模式

DP  design pattern 大话设计模式  中的DP 是设计模式的意思 设计模式的书 ,最经典最原始的就是 GOF 的<设计模式>了. 设计模式的书基本上大多是以这 20 多个模式分开讲.含<大话设计模式> 学了 OOL 写的程序基本上是 OB 的. 只有慢慢掌握了 DP 才能写出真正的 OO 程序. 思想 -> 设计原则 -> DP -> OOD

Head First Design Pattern 读书笔记(2) 观察者模式

Head First Design Pattern 读书笔记(2) Observer Pattern 观察者模式 Observer Pattern 类图 定义 观察者模式:在对象间定义一个一对多的关系,当其中一个的对象发生改变时,所有依赖于这个对象的对象(即观察者们)都会自动更新或做执行某些行为. 几个OO的原测 尽量以松耦合的方式处理对象间关系–>软件工程时候学的"高內聚,低耦合"的好处 关于观察者模式 被观察对象通知观察者可以使用推送的方式(类图中带参数的notifyActi