1. 定义

为了确保一个类有且仅有一个实例,而且自行实例化并向整个系统提供这个实例。

2. 使用场景

确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。例如,创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源,这时候就需要考虑使用单例模式。

3. 机制

创建一个独一无二觉得的对象,有多种方式。但是不管你如何创建一个单例对象,都必须要确保其他开发人员不能创建该单例对象的新的实例。

那么如何做到这一点呢?  答:为了避免其他开发人员实例化你定义的类,可以创建唯一一个构造函数,并将其设置为私有的访问权限。注意,如果创建了其他非私有的构造函数,或者没有创建任何构造函数,其他对象都能够实例化改类。

设计一个单例类的时候,需要确定何时实例化该类的单例对象。一种做法是创建这个类的实例,并将它作为该类的静态成员变量。例如:

private static Factory factory = new Factory();

然后通过一个公共的getFactory()静态方法获得该类的唯一实例。实例代码:

public class Factory{
    private static Factory factory = new Factory ();
    public static Factory getFactory() {
        return factory;
    }
    private Factory() {}
}

如果不希望提前创建单例实例,还可以在第一次需要的时候,延迟初始化它。

if (factory == null)
    factory = new Factory();

延迟不延迟有哪些方面的区别呢? 为什么实例化还有延迟和非延迟?   一般延迟实例化对象有两个原因: 1. 在静态初始化的时候,没有足够的信息对单例对象进行初始化。  2. 选择延迟初始化单例对象与获取资源有关,如数据库连接,没有使用的需求,就没有必要实例化该单例对象。

3. 单例与线程

如果想在多线程环境下延迟初始化一个单例模型,必须避免多个线程同时初始化该单例对象。在多线程环境下,无法保证在其他线程开始执行该方法时,当前线程已经完整的执行完该方法。这可能出现两个线程同时初始化一个单例对象的情况。为了避免这种情况,需要使用双重校验锁机制(Double Check Lock)去协调不同线程对同一方法的执行。

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

单例模式或许是最负盛名的一个设计模式,但是很容易被误用,不要让单例作为创建全局变量的一种花哨方法。因为单例会引入耦合,应减少使用单例模式的类的数量。最好的方式是:类只知道与它协作的对象,不必了解它所需要的限制。 需要注意的是:对象具有唯一性,不代表使用了单例模式。

4. 推荐使用的单例模式实现方式

在应用单例模式时,我们知道懒汉模式、饿汉模式、双重检验锁模式。这些实现方式都有各自的特点和缺陷,其中双重校验锁算性是应用最为广泛的,但是也不是完美的。《Java并发编程实践》这本书给出来一个推荐的实现方式:

public class Singleton {
       // 构造函数
       private Singleton() {}
  
       public static Singleton getInstance(){
      return SingletonHloder.sInstance;
       }

    // 静态内部类
      private static class SingletonHloder {
      private static final Singleton sInstance = new Singleton();
     }
}    

实现方式解读:

当第一次加载Singletion类时并不会初始化sInstance,只有在第一次调用Singleton的getInstance方法时才会导致sInstance被初始化。因此,第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,这种方式不仅能够确保线程安全,也能保证单例对象的唯一性,同时也延迟了单例的实例化,所以这是推荐使用的单例模式的实现方式。

设计模式总结(Java)—— 单例模式的更多相关文章

  1. 【Java设计模式】java单例模式

    解释一下什么是单例模式:     单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些 ...

  2. Java设计模式之《单例模式》及应用场景

    摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6510196.html 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该 ...

  3. Java设计模式之【单例模式】

    Java设计模式之[单例模式] 何为单例 在应用的生存周期中,一个类的实例有且仅有一个 当在一些业务中需要规定某个类的实例有且仅有一个时,就可以用单例模式 比如spring容器默认初始化的实例就是单例 ...

  4. Java设计模式中的单例模式

    有时候在实际项目的开发中,我们会碰到这样一种情况,该类只允许存在一个实例化的对象,不允许存在一个以上的实例化对象,我们将这种情况称为Java设计模式中的单例模式.设计单例模式主要采用了Java的pri ...

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

    原地址:http://blog.csdn.net/xu__cg/article/details/70182988 Java单例模式是一种常见且较为简单的设计模式.单例模式,顾名思义一个类仅能有一个实例 ...

  6. 【设计模式】Java设计模式 - 单例模式

    [设计模式]Java设计模式 - 单例模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 分享学习心得,欢迎指正,大家一起学习成长! 原创作品,更多关注我CSDN: ...

  7. 用java单例模式实现面板切换

    1.首先介绍一下什么是单例模式: java单例模式是一种常见的设计模式,那么我们先看看懒汉模式: public class Singleton_ { //设为私有方法,防止被外部类引用或实例 priv ...

  8. 【白话设计模式四】单例模式(Singleton)

    转自:https://my.oschina.net/xianggao/blog/616385 0 系列目录 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factor ...

  9. 深入Java单例模式【转载】

    在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就单例设计模式详细的探讨一下.   所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在 ...

  10. 【转载】深入Java单例模式

    原文出处:http://devbean.blog.51cto.com/448512/203501 在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就 ...

随机推荐

  1. delphi WebBrowser IPv6

    We discovered one or more bugs in your app when reviewed on iPhone running iOS 11.4 on Wi-Fi connect ...

  2. phpexcel导入导出

    先下载类文件,将类文件放到lib下,然后到入口文件定义一个新的的路径,以便引入文件.    <?php namespace app\index\controller; use think\Con ...

  3. 移动端UL列表无法平滑向下滚动问题

    问题说明: 移动端向上滑动后,,列表无法自动滚动到底部~~而是类似屏幕"沾手"的效果(手离开屏幕直接停止在当前~列表不会自动向下滚动一段) 问题原因: 页面中存在如下代码: 当前页 ...

  4. nexus的安装和简介

    下载nexus Nexus 是Maven仓库管理器,通过nexus可以搭建maven仓库,同时nexus还提供强大的仓库管理功能,构件搜索功能等. 下载Nexus, 下载地址:http://www.s ...

  5. Node Sass does not yet support your current environment解决办法

    在React项目中,使用了sass.之前运行的好好的,今天突然报错,提示当前环境不支持sass模块,然后就百度了下,发现有相同问题的.原来问题是之前开发时node是6.x的版本,几天前更新到最新10. ...

  6. linux目录与文件权限的意义

    现在我们已经知道了Linux系统内文件的三种身份(所有者,用户者,与其他人),知道每种身份都有三种属性(r,w,x),已经能够使用chown,chgrp,chmod去修改这些权限和属性,那么这些文件权 ...

  7. oracle中文乱码的解决方法

    select userenv('language') from dual; NLS_LANG AMERICAN_AMERICA.AL32UTF8

  8. 特大数字之和,返回结果是字符串(考虑到数字特别大,如果相加会产生e)

    自己做的,没有整理代码,还是做出来了: 做这个题时,最总要的一步思路就是,先让长度一致,然后从个位开始,每一个与每一个数字相加,如果大于10,则下一次另外两个数相加时加1 function add(a ...

  9. 1. Go安装

    和任何语言一样,开始使用之前都要先安装好他的开发/编译环境. Go是由谷歌开发的一个开源的编译型的静态语言,编译型语言最大的优点就是效率高运行速度快. Go语言支持Linux,Windows,Mac等 ...

  10. discuz代码转为html代码

    下面附件是来自discuz的一个函数文件(原来是在source/function/function_discuzcode.php位置),已稍微修改: https://files.cnblogs.com ...