美文网首页YLiOS设计模式之道设计
我学设计模式:单例(Singleton)模式

我学设计模式:单例(Singleton)模式

作者: hoxis | 来源:发表于2015-12-31 13:18 被阅读101次

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

要想控制一个类只被创建一个实例,那么首要的问题就是把创建实例的权限收回来,让类自己来负责创建自己类的实例,然后由这个类来提供外部可以访问这个类实例的方法,这就是单例模式的实现方法。

单例模式的结构和实现

单例模式的结构图单例模式的结构图

Singleton:负责创建Singleton类自己的唯一实例,并提供一个getInstance的方法,来外部来访问这个类的唯一实例。

  1. 私有化构造方法
  2. 提供静态的获取实例的方法
  3. 定义存储实例的属性,因为要在静态方法中使用,因此要加上static修饰
  4. 实现控制实例的创建

示例代码

懒汉模式

所谓懒汉模式,既然懒,那么在创建对象实例时就不要着急,在马上要使用对象实例时才会创建,在装载对象时不会创建对象实例。

package com.liuhao.designpattern.singleton;

/**
 * 单例模式懒汉模式
 * 
 * @author liuhao
 * 
 *         2015年7月17日
 */
public class SingletonLazy {
    // 4. 定义一个变量来存储创建好的类实例
    // 5. 因为要在静态方法中使用,因此要加上static修饰
    private static SingletonLazy instance = null;

    // 1. 构造方法私有化,好在内部控制创建实例的数目
    private SingletonLazy() {
    }

    // 2. 定义一个方法为客户端提供类实例
    // 3. 这个方法需要定义成类方法,也就是
    public static SingletonLazy getInstance() {
        // 6. 判断存储实例的变量是否有值
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }

    private String singletonData;// 单例可以有自己的属性

    /**
     * 获取属性的值
     * 
     * @return 属性的值
     */
    public String getSingletonData() {
        return singletonData;
    }

    /**
     * 单例可以有自己的操作方法
     */
    public void singletonOperation() {

    }
}

饿汉模式

所谓饿汉模式,就是在创建对象实例时比较急,在装载类的时候就会创建对象实例。

package com.liuhao.designpattern.singleton;

/**
 * 单例模式饿汉模式
 * 
 * @author liuhao
 * 
 *         2015年7月17日
 */
public class SingletonHungry {
    // 4. 直装载类的时候就会创建对象实例,只创建一次
    private static SingletonHungry instance = new SingletonHungry();

    // 1. 构造方法私有化,好在内部控制创建实例的数目
    private SingletonHungry() {
    }

    // 2. 定义一个方法为客户端提供类实例
    // 3. 这个方法需要定义成类方法,也就是
    public static SingletonHungry getInstance() {
        // 5. 直接使用以及创建好的实例
        return instance;
    }

    private String singletonData;// 单例可以有自己的属性

    /**
     * 获取属性的值
     * 
     * @return 属性的值
     */
    public String getSingletonData() {
        return singletonData;
    }

    /**
     * 单例可以有自己的操作方法
     */
    public void singletonOperation() {

    }
}

其他

单例模式的范围

目前Java实现的单例是一个虚拟机范围的,因为装载类的功能是虚拟机的,所以一个虚拟机在通过自己的ClassLoader装载饿汉模式实现单例时就会创建一个类的实例。

因此如果一个虚拟机里面有很多个ClassLoader,而这些ClassLoader都装载某个类的话,就会产生多个实例。

单例模式的调用顺序

  • 懒汉模式
单例模式的调用顺序单例模式的调用顺序
  • 饿汉模式
单例模式的调用顺序单例模式的调用顺序

体现的一些思想

  • 延迟加载
    懒汉模式中,一开始没有加载所需的资源或者数据,一直等到马上就要使用了才加载,即所谓的“延迟加载”。

  • 缓存
    当某些资源或数据被频繁的使用,而且它们是存储在系统外部的(如数据库、硬盘),那么每次操作都要从数据库获取,速度会很慢,操作性能问题。

一个简单的方法就是把这些数据缓存到内存中,每次操作的时候先到内存里找,若有则直接使用;若果没有再获取它并设置到缓存中。

缓存是一种典型的空间换取时间的方案。

线程安全

  1. 不加同步的懒汉模式是线程不安全的。比如,有线程A、B同时调用getInstance方法,那就可能导致并发问题,如图。


    懒汉模式线程冲突懒汉模式线程冲突
  2. 如何实现懒汉模式的线程安全

    1. 加上关键字synchronized,如下
    public static synchronized SingletonLazy getInstance() {}
    
    1. 双重检查加锁。不是在每次进入getInstance时都需要同步,而是先不同步,进入方法后,先检查实例是否存在。如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。
      双重检查加锁机制的实现需要使用volatile关键字,被它修饰的变量的值将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能够正确的处理该变量。
      具体实现:
    public static SingletonVolatile getInstance() {
        // 检查实例是否存在,不存在则进入到同步块
        if (instance == null) {
            // 同步块,线程安全地创建实例
            synchronized (SingletonVolatile.class) {
                // 再次检查实例是否存在,不存在则真正的创建实例
                if (instance == null) {
                    instance = new SingletonVolatile();
                }
            }
        }
        return instance;
    }
    

    这种实现方式既可以实现线程安全,同时也不会对性能造成太大的影响。

  3. 饿汉模式是线程安全的。


如果觉得有用,欢迎关注我的微信,有问题可以直接交流:

你的关注是对我最大的鼓励!你的关注是对我最大的鼓励!

相关文章

  • JAVA设计模式 - 单例模式

    JAVA设计模式 - 单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一...

  • 设计模式

    史上最全设计模式导学目录(完整版) 单例模式(Singleton Pattern) 确保对象的唯一性——单例模式 ...

  • 单例模式

    3、单例模式(Singleton) 单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象...

  • 设计模式——单例模式

    设计模式——单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,这种类型...

  • 设计模式-单例模式(Singleton)

    单例模式(Singleton) 单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保...

  • 设计模式

    单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式...

  • 设计模式与软件原则 (二):单例设计模式

    单例设计模式(Singleton Design Pattern) 单例设计模式是一种创造(creational)设...

  • 设计模式--单例模式

    单例模式(singleton) 单例模式最初的定义出现于《设计模式》(Addison-Wesley,1994) 单...

  • 设计模式《一》单例模式

    单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属...

  • 设计模式之单例模式详解(附源代码)

    单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属...

网友评论

本文标题:我学设计模式:单例(Singleton)模式

本文链接:https://www.haomeiwen.com/subject/smoihttx.html