设计模式学习-单例模式

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.单例模式详解
时间: 2024-10-06 01:09:58

设计模式学习-单例模式的相关文章

java设计模式学习 ----- 单例模式(Singleton)

单例模式(Singleton) 单例对象(Singleton)是一种经常使用的设计模式. 在Java应用中,单例对象能保证在一个JVM中,该对象仅仅有一个实例存在.单例模式也分三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有几个长处: 1.某些类创建比較频繁,对于一些大型的对象,这是一笔非常大的系统开销. 2.省去了new操作符,减少了系统内存的使用频率,减轻GC压力. 3.有些类如交易所的核心交易引擎.控制着交易流程,假设该类能够创建多个的话,系统全然乱了.(比方一个军队出现了多个司令员

(@WhiteTaken)设计模式学习——单例模式

单例模式,个人理解就是,使用了这个模式,可以保证一个类只生成唯一的实例对象.就是在整个程序中,这个类只存在一个实例对象. GoF对单例模式的定义:保证一个类,只有一个实例存在,同时提供能对该实例加以访问的全局访问方法. 客户端的代码用来测试,获取到的实例只有一个.直接上代码. 1 public class MainClass { 2 public static void main(String[] args) { 3 Person person1=Person.getPerson();//获取P

js设计模式学习 --- 单例模式1

什么单例模式 定义: 保证一个类仅有一个实例,并提供一个访问它的全局访问. 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池.全局缓存.浏览器中的window 对象等.在JavaScript 开发中,单例模式的用途同样非常广泛.试想一下,当我们单击登录按钮的时候,页面中会出现一个登录浮窗,而这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建. 实现单例模式 <script type="text/javascrip

javascript设计模式学习——单例模式

单例模式:又被称为单体模式,是只允许实例化一次的对象类. 运用: 1.用一个对象来规划一个命名空间(如:JQuery库,单例模式就为它提供了一个命名空间),井井有条地管理对象上的属性与方法. 2.通过单例模式来管理代码库的各个模块 模块化的概念由来已久,并且在JS中也有很长久的使用历史.通常我们在编写代码时,会将复杂的问题根据实际情况进行合理的拆分,让代码更具备可读性与可维护性.因此一个模块可以理解为整体的一部分.而且随着JS应用复杂度的提高,模块化的应用也变成了必须. 在之前的JS中,没有专门

设计模式学习-单例模式

定义:确保某一个类只有一个实例,而且自行实例化向整个系统提供整个实例 使用场景: 要求生产唯一序号的环境 在整个项目中需要一个共享访问点或共享数据,例如程序计数器 创建一个对象需要消耗的资源过多 需要定义大量的静态常量或静态方法的环境 实例: package cn.lonecloud.singleton; /** * @author lonecloud * @version v1.0 * @date 下午3:44 2018/3/16 */ public class DemoSingleton {

java/android 设计模式学习笔记(一)---单例模式

前段时间公司一些同事在讨论单例模式(我是最渣的一个,都插不上嘴 T__T ),这个模式使用的频率很高,也可能是很多人最熟悉的设计模式,当然单例模式也算是最简单的设计模式之一吧,简单归简单,但是在实际使用的时候也会有一些坑. PS:对技术感兴趣的同鞋加群544645972一起交流 设计模式总目录 java/android 设计模式学习笔记目录 特点 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式的使用很广泛,比如:线程池(threadpool).缓存(cache).对

【我的设计模式学习】单例模式

单例模式大概是最直观的一种设计模式了.尽管直观却不简单. 数学与逻辑学中,singleton定义为"有且仅有一个元素的集合".单例模式可以如下定义:"一个类有且仅有一个实例,并且自行实例化向整个系统提供". 我比较喜欢Design Patterns 一书中的描述"保证一个类仅有一个实例,并提供一个访问它的全局访问点". 单例模式的特点 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例

设计模式学习01—单例模式

一.动机与定义 系统中有些资源只能有一个,或者一个就够,多个浪费.例如一个系统只能有一个窗口管理器或文件系统.一个系统只能有一个计时器或序号生成器.web系统只能有一个页面计数器等等.此时,最好就需要把这些资源设置成有且仅有一个实例. 代码中也就是如何保证一个类只有一个实例并且这个实例能够被访问呢?只有一个实例的就意味着不能让其他类来实例化,也就是只能自己实例化自己.能够被访问也就意味着自身要对外提供全局方法来获取到这个实例,这就是单例模式. 单例模式定义:确保某一个类只有一个实例,而且自行实例

从源码中学习设计模式系列——单例模式序/反序列化以及反射攻击的问题(二)

一.前言 这篇文章是学习单例模式的第二篇,之前的文章一下子就给出来看起来很高大上的实现方法,但是这种模式还是存在漏洞的,具体有什么问题,大家可以停顿一会儿,思考一下.好了,不卖关子了,下面我们来看看每种单例模式存在的问题以及解决办法. 二.每种Singleton 模式的演进 模式一 public class LazySingleton { private static LazySingleton lazySingleton = null; private LazySingleton() { }

Java设计模式学习01——单例模式(转)

原地址:http://blog.csdn.net/xu__cg/article/details/70182988 Java单例模式是一种常见且较为简单的设计模式.单例模式,顾名思义一个类仅能有一个实例,并且向整个系统提供这一个实例. 单例模式的特点: 单例类仅能有一个实例. 单例类必须为自己创建实例. 单例类必须向外界提供获取实例的方法. 以下是几种实现方法 一.懒汉式单例(能够延时加载) public class SingleTon { private static SingleTon ins