设计模式讲解与代码实践(五)——单例

本文来自李明子csdn博客(http://blog.csdn.net/free1985),商业转载请联系博主获得授权,非商业转载请注明出处!

1 目的

单例(Singleton)保证一个类仅有一个实例,并提供一个访问它的全局访问点。

2 基本形态

单例的基本形态如类图2-1所示。
设计模式讲解与代码实践(五)——单例_第1张图片
图2-1 单例类图

3 参与者

从图2-1中可以看到,单例设计模式只涉及到Singleton一个参与者。
3.1 Singleton
Singleton类是单例类。通过将构造函数声明为私有来阻止从外部对类实例化。同时,Singleton提供一个获取自身实例的静态方法Instance。该方法被调用时判断自身类型的成员uniqueInstance是否为null,如果是则实例化对象返回,并为uniqueInstance赋值;如果不是则返回uniqueInstance。
关于Singleton实例化的时机除了上文所述的“在第一次获取实例时”外,还可以在“类加载时”。此时,静态成员变量uniqueInstance在声明时用构造方法赋值,类被加载时——任意静态成员方法或任意非常量静态成员变量第一次被访问时将实例化Singleton。
另外,Singleton还包含了获取单例数据的方法GetSingletonData和单例内部数据操作方法SingletonOperation。

4 代码示例

单例的实现非常简单,一些现代的IDE(如IntelliJ)甚至将其作为一种类的创建类型而将其模板化。下面是IntelliJ自动生成的(注释除外)单例代码。

package demo.designpattern.singleton;

/**
 * 单例
 * Created by LiMingzi on 2017/7/4.
 */
public class Singleton {
    /**
     *单例对象
     */
    private static Singleton ourInstance = new Singleton();

    /**
     * 获取单例实例
     * @return
     */
    public static Singleton getInstance() {
        return ourInstance;
    }

    /**
     * 构造方法
     */
    private Singleton() {
    }
}

5 应用场景

要回答单例模式在具体业务场景下如何应用这个问题,首先要了解单例模式在技术层面为我们带来了什么。本章将首先从技术层面分析单例模式带给我们的对象使用特点,进而举例说明单例模式在业务场景中的使用。
5.1 基于技术层面的场景分析
单例,究其本质是在全局仅实例化类的一个实例。之后,对该类的实例的访问均为对同一实例的访问。那么从“只实例化一次”和“全局访问同一实例”这两点出发,我们可以看到单例模式的对象创建及其访问拥有如下特点:

  1. 构造方法只执行一次;
  2. 对类的成员的访问均发生在同一对象上,即同一时刻得到的结果相同;
  3. 对类的成员的操作均作用在同一对象上;

据此,我们可以推导出单例模式在满足以下技术场景时可以得到有效利用:

  1. 对象承载着全局数据共享与传播的职责,即作为“全局变量”使用;
  2. 对象的构造过程复杂、耗时,对于各可能的主调方法其构造过程一致;
  3. 对对象的成员的修改是全局性的,对任意主调方法而言均有意义;
  4. 对象需要在不同主调环境下频繁使用,大量创建将严重消耗内存;
    当然,单例作为典型的时空转换模式也存在单对象常驻内存的问题。不过,对于当前服务器的典型配置,这个问题是可以忽略不计的。

5.2 业务场景举例
鉴于5.1节中基于技术层面的场景分析,以下几个业务场景可以考虑使用单例。
5.2.1 锁
锁是我们并发访问控制的有效手段。我们可以利用单例模式“仅有一个实例”的特点来实现锁。
5.2.2 全局计数器
作为锁的变种,全局计数器常被用来记录对某个资源的访问次数,此时使用单例是非常适合的。
5.2.3 配置项
一般的产品、项目均会有大量的配置项,他们往往持久化于配置文件或数据库中。它们的特点是被多个业务模块访问,甚至是频繁访问,而在项目运行过程中进行修改的频率是较低的。
可以使用单例模式封装配置项,在单例实例化时一次性加载所有的配置项,并提供根据配置项key查询值的方法供业务模块使用。
5.2.4 主控
对于线程池、资源池、连接池、任务链、消息队列等公共资源进行分配的主控类通常使用单例模式实现。因为它们均有“全局唯一性”的特点。
5.2.5 对象创建者
一些专用于对象创建的类在业务代码中被频繁实例化,这些类对象自身并不包含维持状态的成员变量,其存在价值仅是提供创建对象的公共方法。对于这类对象创建者可以通过使用单例模式节省频繁实例化带来的开销。

你可能感兴趣的:(算法与程序设计,设计模式,java,架构设计,设计模式讲解与代码实践)