码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式学习-单例模式

时间:2016-04-29 07:03:20      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:

1.定义

一个类有且仅有一个实例,并且自行实例化向整个系统提供

2.类图

技术分享

3.代码示例

网上最多有8中实现方式,其中包括了很多非线程安全的实现。我觉得没有必要。这里提供单例模式的两种实用实现,均为线程安全,这里推荐第一种实现,即实现了线程安全,又实现了懒加载

package com.zhaoyangwoo.singleton;

/**
 * Created by john on 16/4/28.
 */
public class Singleton {

   private Singleton() { } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } //通过内部类机制 实现懒加载 private static class SingletonHolder { static final Singleton INSTANCE = new Singleton(); } }

 

package com.zhaoyangwoo.singleton;

/**
 * Created by john on 16/4/28.
 *
 */
public class Singleton2 {/**
     * 饿汉式
     */
    private static Singleton2 instance = new Singleton2();

    private Singleton2() {
    }

    public static Singleton2 getInstance() {
        return instance;
    }

}

另外这里特别提到一下,对于双重检查锁定的实现,我不是很推荐,因为其在JDK1.4版本前是有失败的可能性的。

原因在于:初始化Singleton和将对象地址写到instance字段的顺序是不确定的。在某个线程new Singleton()时,在构造方法被调用之前,就为该对象分配了内存空间并将对象的字段设置为默认值。此时就可以将分配的内存地址赋值给instance字段了,然而该对象可能还没有初始化。此时若另外一个线程来调用getInstance,取到的就是状态不正确的对象。自JDK1.5后对volatile关键字描述的字段,JVM是不会对其读写进行重排序优化,问题才得以解决。

package com.zhaoyangwoo.singleton;

/**
 * Created by john on 16/4/28.
 * 双重检查锁定
 */
public class Singleton3 {

    private static volatile Singleton3 instance = null;

    private Singleton3() {
    }

    public static Singleton3 getInstance() {
        if (instance == null) {
            synchronized (Singleton3.class) {
                if (instance == null) {
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
} 

4.应用场景举例

  • 日志管理应用和配置文件的读写
  • 创建一个对象的消耗很大,例如访问IO,数据库等

5.JAVA源码中的模式实现

java.lang.Runtime对象的创建,从源码可以看出这里是用了饿汉式的实现方式。同样使用到单例模式的有java.lang.System等

package java.lang;

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    public static Runtime getRuntime() {
        return currentRuntime;
    }

    /**
     * Don‘t let anyone else instantiate this class
     */
    private Runtime() {
    }

    ...
}

 

6.思考

思考如下两个问题

  • 单例模式状态修改 

一般单例模式是不保存或者说不改变实例的状态,如果单例模式涉及到状态修改/保存,那么其方法调用需要考虑到多线程同步问题

  • 单例模式vs静态类

    工作中需要读取一个配置property文件,之前的实现是这样的:

public class PropertiesGetter {
    
    private static Properties privateProperties;

    static {
            privateProperties.load(new FileInputStream(System.getProperty("configHome/web.properties"));
    }

    public static String getStringProperty(String propertyNameEnum) {
        return privateProperties.containsKey(propertyNameEnum)?privateProperties.getProperty(propertyNameEnum):null;
    }
    //删减无关代码
    ...
    
}

//调用是这样的
PropertiesGetter.getStringProperty("XXXX");

 

  现在改成了单例模式

public class PropertiesGetter {

    private PropertiesGetter() {
    }

    private static final PropertiesGetter instance = new PropertiesGetter();

    public static PropertiesGetter getInstance() {
        return instance;
    }

    private static Properties privateProperties = new Properties();

    static {
        privateProperties.load(new FileInputStream(System.getProperty("configHome/web.properties"));
    }

    public String getStringProperty(PropertiesNameEnum propertyNameEnum) {
        return privateProperties.containsKey(propertyNameEnum)?privateProperties.getProperty(propertyNameEnum):null;
    }

    //无关代码
    ...
}

//调用
PropertiesGetter.getInstance().getStringProperty("XXXX");

 就单单这个例子而言,我也说不出两种实现方式孰优孰劣?看官有想法请指教

7.参考

1.再议单例模式和静态类 
2.单例模式的7种写法
3.单例模式详解

设计模式学习-单例模式

标签:

原文地址:http://www.cnblogs.com/zhaoyanghoo/p/5442540.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!