设计模式学习(三):确保对象的唯一性—单例模式

一、简介

      单例模式是用于创建那些在软件系统中独一无二的对象。

二、单例模式的意图

      在实际开发过程中经常遇见这样的情况,为了节约系统资源,有时需要确保系统中某个类只有唯一一个实例,当这个唯一实例创建成功之后,无法再创建一个同类型的其他对象,所有的操作都只能基于这个唯一实例。例如,Windows任务管理器在系统中有且仅有一个。

三、单例模式概述

(1)概念

单例模式:确保某一类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类成为单例类,它提供全局访问的方法。

(2)类图

(3)核心代码

 1 public class Singleton
 2 {
 3     //私有构造函数
 4     private Singleton(){}
 5     
 6     //静态变量
 7     private static Singleton instance = null;  
 8    
 9     //公有的静态方法返回该实例
10     public static Singleton GetInstance()
11     {
12           if(instance == null)
13           {
14                   instance = new Singleton();
15           }
16           return instance;
17     }   
18 }

说明:

①为了确保Singleton实例的唯一性,需要禁止类的外部直接使用new来创建对象,因此需要将Singleton的构造函数的可见性改为private。

②为了让外界可以访问这个唯一实例,需要在Singleton中定义一个静态的Singleton类型的私有变量。

③为了让外界可以访问这个唯一实例,需要增加一个公有的静态方法来返回这个唯一实例。

(4)单例模式三要点

①某个类只能有一个实例(通过私有构造函数实现)。

②它必须自行创建这个实例。

③它必须自行向整个系统提供这个实例(通过公有的静态方法来实现)。

四、饿汉式单例与懒汉式单例

<1>饿汉式单例

 当类被加载时,静态变量instance会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建。

 ①类图

②代码

 1 public class EagerSingleton
 2 {
 3     private static EagerSingleton instance = new EagerSingleton();
 4      
 5     private EagerSingleton(){}
 6     
 7     public static EagerSingleton GetInstance()
 8     {
 9           return instance;
10     }  
11 }

<2>懒汉式单例

懒汉式单例在第一次调用GetInstance()方法时实例化,在类加载时并不自行实例化,这种技术又称为延迟加载技术,即需要的时候再加载实例。

①类图

②代码

 1 public class LazySingleton
 2 {
 3       private static LazySingleton instance = null;
 4 
 5       private LazySingleton(){}
 6 
 7       public static LazySingleton GetInstance()
 8       {
 9              if(instance == null)
10              {
11                    instance = new LazySingleton();
12              }
13              
14              return instance;
15       }
16 }

<3>两种模式的比较

      饿汉式单例类在类加载时就将自己实例化,它的优点在于无须考虑多线程访问问题,可以确保实例的唯一性;从调用速度和反应时间角度来讲,由于单例对象一开始就被创建,因此要优于懒汉式单例。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该对象就需要创建,因此从资源利用效率角度来讲,饿汉单例不及懒汉单例,而且在系统加载时由于需要创建懒汉式单例对象,加载时间可能会比较长。

     懒汉式单例类在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处理好多线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的几率比较大,需要通过双重检查锁定机制进行控制,这将导致系统性能受到一定影响。

五、单例模式总结

1.主要优点

(1)单例模式提供了对唯一实例的受控访问。

(2)由于系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。

(3)允许可变数目的实例。基于单例模式,开发人员可以自行扩展,使用与控制单例对象相似的方法来制定个数的实例对象,既节省系统资源,又解决了单例模式对象共享过多有损性能的问题。

2.主要缺点

(1)由于单例模式中没有抽象层,因此单例类的扩展有很大困难。

(2)单例类的职责过重,在一定程度上违背了单一职业原则。因为既提供了业务方法,有提供了创建对象的方法,将对象的创建和对象本身的功能耦合在了一起。

(3)很多面向对象预言的运行环境都提供了自动垃圾回收技术,因此,如果实例化的共享对象长时间不利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致共享的单例对象状态的丢失。

3.使用场景

(1)系统只需要一个实例对象。例如系统要求提供一个唯一的序列号生成器或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。

(2)客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

 

 

posted @ 2014-03-07 10:30  鱼不吐泡泡  阅读(368)  评论(0编辑  收藏  举报