设计模式可以帮助我们改善系统的设计,增强 系统的健壮性、可扩展性,为以后铺平道路。 我们为什么要学习设计模式 ??? 设计模式可以帮助我们改善系统的设计,增强 系统的健壮性、可扩展性,为以后铺平道路。
Singleton Pattern 单例模式 组长:田大海 组员:章凯、刘宇轩、陈梁、曾博晖、陈柱、 王子剑
什么是单例模式? 单例模式是一种常用的软件设计模式。在它的核心 结构中只包含一个被称为单例类的特殊类。 通过单例模式可以保证系统中一个类只有一个实例 而且该实例易于被外界访问,从而方便控制实例个数以 及节约系统资源。
单例类的特征—— 单例类只能有一个实例 单例类必须自行创建自己的唯一实例 单例类必须自行为整个系统提供这一实例
什么样的情况下,我们需要单例模式? 类的任意一个实例对象没 有异于其他实例对象的状 态。也就是说无论实例化 出多少个对象,都是一样 的,不但对于系统性能方 面没有任何额外贡献,而 且还会浪费系统资源。 当类有两个或者两个以上的实例对象的话,会产生程序错误或者与现实相违背的逻辑错误。
For Example: Windows的任务管理器。一台正常的计算机上是不可能同时打开 两个任务管理器的。 windows的回收站。在整个系统运行过程中,回收站一直维护着 仅有的一个实例。
public class Singleton { //一个静态的实例 private static Singleton singleton; //私有化构造函数 private Singleton(){} //给出一个公共的静态方法返回一个单一实例 public static Singleton getInstance(){ if (singleton == null) { singleton = new Singleton(); } return singleton; 最容易想到、最原始 的单例模式的构造方式
真的可以保证只创造一个实例吗??? 1.静态实例,带有static关键字的属性在每一个类中都 是唯一的。 2.限制客户端随意创造实例,即私有化构造方法,此为保 证单例的最重要的一步。 3.给一个公共的获取实例的静态方法。 4.判断只有持有的静态实例为null时才调用构造方法创 造一个实例,否则就直接返回。 真的可以保证只创造一个实例吗???
public class Singleton { //一个静态的实例 private static Singleton singleton; //私有化构造函数 private Singleton(){} //给出一个公共的静态方法返回一个单一实例 public synchronized static Singleton getInstance(){ if (singleton == null) { singleton = new Singleton(); } return singleton; 考虑到多线程并发
将整个获取实例的方法同步,这样在一个线程访 问这个方法时,其它所有的线程都要处于挂起等待状态, 避免了刚才同步访问创造出多个实例的危险。 糟糕的设计!!!造成了很多无谓的等待。
public class Singleton { //一个静态的实例 private static Singleton singleton; //私有化构造函数 private Singleton(){} //给出一个公共的静态方法返回一个单一实例 public static Singleton getInstance(){ if (singleton == null) { synchronized (this) { singleton = new Singleton(); } return singleton; 双加锁模式
这种模式的优点在于:它只是在当前实例为null, 也就是实例还未创建时才进行同步,否则就直接返 回已创建好的实例。这样就节省了很多无谓的线程 等待时间,同时还保证了线程安全。 推荐
public class Singleton { private Singleton(){} public static Singleton getInstance(){ return SingletonInstance.instance; } private static class SingletonInstance{ static Singleton instance = new Singleton(); 静态内部类
一个类的静态属性只会在第一次加载类时初始化,这是 JVM帮我们保证的,所以我们无需担心并发访问的问题。 所以在初始化进行一半的时候,别的线程是无法使用的, 因为JVM会帮我们强行同步这个过程。另外由于静态变 量只初始化一次,所以singleton仍然是单例的。 推荐
public class Singleton { private static Singleton singleton = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return singleton; } 其他方式
这种方式最主要的缺点就是一旦我访问了Singleton的任何其他的 静态域,就会造成实例的初始化,而事实是可能我们从始至终就 没有使用这个实例,就会造成内存的浪费。 不过在有些时候,直接初始化单例的实例也无伤大雅,对项目几 乎没什么影响。比如我们在应用启动时就需要加载的配置文件等, 就可以采取这种方式去保证单例。 推荐
单例模式的优点—— 一、实例控制 单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所 有对象都访问唯一实例。 二、灵活性 因为类控制了实例化过程,所以类可以灵活更改实例化过程。 三、节省空间,减少不必要的浪费。
谢谢大家!