欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-17 18:57:48
...

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

 

单例模式的特点如下:

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 看在打字不易的份上,打赏一个吧

Java设计设计模式之单例模式(Singleton)
            
    
    博客分类: J2SE 设计模式JavaSingleton单例模式 

 

参考资料:

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

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