Java设计设计模式之单例模式(Singleton)

单例模式在日常应用开发过程中被大量使用到,如在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。

单例模式的特点如下:

1、运行时只有一个实例供其他对象使用,同时只允许创建唯一一个实例

2、对象的初始化工作由自身来完成

3、从对象的加载方式来分,可分为乐观加载和悲观加载两种方式

单例模式应用的场景一般发现在以下条件下:
(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。

设计单例类的过程中,有些人觉得分情况考虑,你可以设计成线程安全的单例模式和线程不安全的,其实在现在互联网应用满天飞的今天,养成良好的习惯,设计的时候你只考虑线程安全的会对以后的帮助比较大,至于性能方面的考虑,可以不用在乎, 毕竟通常情况下应用的性能瓶颈往往都是架构设计层面导致的,和一个小小的模块内部的实现细节有关系,但影响没有想象中的那么大。系统的核心性能问题还是要从架构层面入手去考虑设计。

1、乐观加载的单例模式

/**
 * 乐观加载
 * 
 * @author Administrator
 * @version $Id: Singleton.java, v 0.1 2017年3月11日 下午6:59:43 Administrator Exp $
 */
public class Singleton {

    /**  */
    private static Singleton _inst = null;

    /**
     * 乐观加载,相信在使用时加载也来得及
     * 
     * @return
     */
    public static Singleton getInstance() {
        if (_inst == null) {
            synchronized (Singleton.class) {
                _inst = new Singleton();

                System.out.println("init instance first time");
            }
        }

        System.out.println("its ready, just get it");
        return _inst;
    }

    public static void main(String[] args) {
        Singleton.getInstance();
        Singleton.getInstance();
        Singleton.getInstance();
    }
}

运行结果:

init instance first time
its ready, just get it
its ready, just get it
its ready, just get it

这种方式的优势是,在系统启动过程中减少了系统启动的时间,单例类内部的实际加载过程是在系统第一次被使用时才去完成,因此这种模式也被叫做惰性单例模式。

这种模式下的类实例初始化动作需要比较小心,因为初始化是在第一次使用时,因此类实例在定义时,无法定义成常量,最多只能定义成一个静态的对象,而第一次触发初始化动作的请求有可能并发进来很多,为了避免短时间内的频繁初始化带来一些不可预期的结果,在初始化的过程中需要选择在同步块中完成。

2、悲观加载的单例模式

/**
 * 悲观加载
 * 
 * @author Administrator
 * @version $Id: Singletonn.java, v 0.1 2017年3月11日 下午7:09:40 Administrator Exp $
 */
public class Singletonn {
    /**  */
    private static final Singleton _inst = new Singleton();

    /**
     * 乐观加载,相信在使用时加载也来得及
     * 
     * @return
     */
    public static Singleton getInstance() {

        System.out.println("its ready, just get it");
        return _inst;
    }

    public static void main(String[] args) {
        Singleton.getInstance();
    }
}

这种方式比较简单,对象实例的初始化是通过一个常量直接完成的,但经常需要初始化的实例往往要比我们例子复杂很多,所以会出现一些这两种方式综合使用的变种单例模式

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 悲观加载
 * 
 * @author Administrator
 * @version $Id: Singletonn.java, v 0.1 2017年3月11日 下午7:09:40 Administrator Exp $
 */
public class Singletonn {
    /**  */
    private static final Map<String, Singleton> _inst = Collections
        .synchronizedMap(new HashMap<String, Singleton>());

    static {

        synchronized (_inst) {
            _inst.put("key1", Singleton.getInstance());
            _inst.put("key2", Singleton.getInstance());
            _inst.put("key3", Singleton.getInstance());
        }
    }

    /**
     * 乐观加载,相信在使用时加载也来得及
     * 
     * @return
     */
    public static Singleton getInstance() {
        return new Singleton();
    }

    public static void main(String[] args) {
        Singleton.getInstance();
    }
}

其中,静态块中的内容,我们可以理解为,是在初始化过程中需要完成的一系列的业务处理,当然这里还会有其他很多的单例类演化方式,但万变不离其宗,只要了解了基本的情况,后面的变种,只是自己在后续的实际使用场景中灵活处理的方式而已,没必要去死记这些东西。

各位看官,原创不易啊,转载请注明出处: http://danlley.iteye.com 看在打字不易的份上,打赏一个吧

参考资料:

http://blog.csdn.net/tanyujing/article/details/14160941

http://blog.csdn.net/jason0539/article/details/23297037/

猜你喜欢

转载自danlley.iteye.com/blog/2361572