[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍单例模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk8

-------------------------------------------------------------------------------------------------------------------------------------

经典问题:

日志Logger对象。

思路分析:

要点一:在任意时刻,系统中只能有数量小于等于一个的该对象。

要点二:无论是自己创建,还是被其他对象创建或引用,均不能破坏唯一性。

【由于单例模式是较为常用的一种设计模式。所以我们调整一下顺序,先说明概念,然后在展示示例代码】

模式总结:

单例模式结构图:

单例模式:

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

组成部分:

Singleton(单例类):在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。

模板代码:

懒汉式单例:

特点:

  1. 延迟加载,只有到真正使用是才生成一个单例对象供调用对象使用。并且,以后不会再生成新的该对象。
  2. 拥有一个private修饰的静态变量
  3. 拥有一个private修饰的构造方法,方式被外部的对象调用。
  4. 拥有一个public修饰的静态工厂方法,返回一个具体的实例。
package com.csdn.ingo.gof_Singleton;public class Singleton {private static Singleton instance;private Singleton(){}public static Singleton getInstance(){if(instance==null){instance = new Singleton();}return instance;}
}
package com.csdn.ingo.gof_Singleton;public class WIndow {public static void main(String[] args) {Singleton s1 = Singleton.getInstance();Singleton s2 = Singleton.getInstance();if(s1==s2){System.out.println("s1==s2");}}
}

Singleton通过将构造方法限定为private避免了本类在外部进行实例化操作,在同一个虚拟机的范围内,Singleton的唯一示例只能通过getInstance()方法进行获取。(事实上,通过Java的反射机制,能够访问private类型的方法,此处对此问题暂不做讨论)

懒汉式单例的问题:

当发生多线程同时使用该对象时,会发生线程不安全的问题。很有可能生成多个对象。

解法:

增加线程锁,双重锁检查,静态内部类(推荐)等方法。

①增加同步锁:
public static synchronized Singleton getInstance() {  if (single == null) {    single = new Singleton();  }    return single;
} 
②双重锁检查:
public static Singleton getInstance() {  if (singleton == null) {    synchronized (Singleton.class) {    if (singleton == null) {    singleton = new Singleton();   }    }    }    return singleton;   }  
③静态内部类:(内部类在调用时才进行加载)
public class Singleton {    private static class LazyHolder {    private static final Singleton INSTANCE = new Singleton();    }    private Singleton (){}    public static final Singleton getInstance() {    return LazyHolder.INSTANCE;    }
} 

饿汉式单例:

特点:

  1. 在类进行加载时就创建了一个单例对象,并且之后一直使用该对象。
  2. 拥有一个private final static 修饰的,并且自身带初始化的变量。
package com.csdn.ingo.gof_Singleton.two;public class Singleton {private Singleton() {}private final static Singleton instance = new Singleton();public static Singleton getInstance() {return instance;}
}

以上两种单例模式区别:

线程安全性:

饿汉式的单例模式:一定是线程安全的。懒汉式的单例模式:其自身是非线程安全的,但是能够通过其他①②③三种方式实现安全性。

性能:

饿汉式的单例模式:

在启动实例化过程时,就会创建一个单例对象。因此,在时间上而言,实例化启动的时间较长,使用时的调用时间相对较短。另外,该单例对              象会一直存在于内存当中。

懒汉式的单例模式:

在启动实例化过程中,没有创建一个单例对象,而是在使用时才创建一个单例对象。因此,在时间上而言,实例化启动的时间较短,使用时的             调用时间相对教程。另外,在实例化之后,该单例对象也会一直存在于内存当中。

除此之外:

上文第①种方式:每次都需要使用同步锁,对性能会产生不利影响。

上文第②种方式:在第一次调用时,使用同步锁。后续不再使用同步锁。对性能影响较为有限。

上文第③种方式:内部类在初始化时未生成一个单例对象,而是等到第一次调用时才生成。在调用时,由于Classloader的特殊性,保证实例化的对象有且只有一个单例对象。因此,其表现效果类似于②。

枚举式单例:

特点:

  1. 通过枚举定义的方式声明与使用单例对象
  2. 线程安全:枚举的创建过程本身是线程安全的
  3. 不会因为序列化而产生新实例:在传统的单例模式中,一旦实现了Serializable接口,其就不再是单例的对象了,因为readObject()方法内次总是返回一个新的示例对象,此过程类似于Java中的构造器。而对于枚举实现单例,其实从JVM中防止了此问题。
package com.csdn.ingo.gof_Singleton.thire;public enum Singleton {Instance; // 定义一个枚举的元素,就代表Singleton的一个实例private Singleton() {}
}

双重锁Volatile检查的单例模式:

特点:

  1. volatile关键字:保证该对象始终是最新的值(在Java1.5版本之后上文的双重锁存在漏洞,具体原因,请各位看官查看volatile解释即可)
  2. 其他类似于上文双重锁检查。
package com.csdn.ingo.gof_Singleton.five;public class Singleton {private volatile static Singleton singleton;private Singleton() {}public static Singleton getInstance() {if (singleton == null) {synchronized (Singleton.class) {if (singleton == null) {singleton = new Singleton();}}}return singleton;}
}

反思:

应用场景:

  1. 在系统内只需要有且只有一个该对象时,如日志对象,ID生成器对象,等等。
  2. 客户端对单例对象只允许使用一个公共访问点。

优点:

  1. 单例模式提供了对实例对象的唯一入口。严格控制了客户的方式与路径。
  2. 节约系统资源,节约该对象的响应时间。
  3. 单例模式可以扩展为指定数量的对象生成器。其效果类似于连接池的创建过程,取得资源与效率的平衡。

缺点:

  1. 单例模式不符合“开闭原则”。对单例的维护只能修改单例类本身。
  2. 单例模式不符合“单一职责原则”。单例类本身负责创建对象,有包含了对象的其他方法。
  3. Java垃圾回收机制会将长时间未使用的,实例化的共享的单例对象进行回收,导致该对象的状态丢失。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---单例模式 结束

参考资料:

图书:《大话设计模式》

其他博文:

http://blog.csdn.NET/lovelion/article/details/7563445

http://cantellow.iteye.com/blog/838473

https://my.oschina.net/zhoujy/blog/134958

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

http://www.cnblogs.com/zhengbin/p/5654805.html

http://javarevisited.blogspot.jp/2012/07/why-enum-singleton-are-better-in-java.html

被说了很多遍的设计模式---单例模式相关推荐

  1. 设计模式-单例模式-注册式单例模式-枚举式单例模式和容器式单例模式在Java中的使用示例

    场景 设计模式-单例模式-饿汉式单例模式.懒汉式单例模式.静态内部类在Java中的使用示例: 设计模式-单例模式-饿汉式单例模式.懒汉式单例模式.静态内部类在Java中的使用示例_霸道流氓气质的博客- ...

  2. 设计模式----创建型设计模式(单例模式、工厂方法模式、构建者模式)

    创建型设计模式 单例模式(Singleton Pattern) 单例模式介绍 代码演示 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全, ...

  3. 软件设计模式“单例模式”和“工厂模式”

    软件设计模式"单例模式"和"工厂模式" 单例模式 什么是单例模式 单例模式的实现方式有哪些 单例模式的优缺点 单例模式的应用场景 总结 工厂模式 什么是工厂模式 ...

  4. 设计模式——单例模式、工厂模式

    设计模式--单例模式.工厂模式 一.六大设计原则 开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭.在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热 ...

  5. Python设计模式-单例模式

    Python设计模式-单例模式 基于Python3.5.2,代码如下 #coding:utf-8 import threading import timeclass Singleton(object) ...

  6. Android设计模式——单例模式(Singleton)

    二十三种设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元 ...

  7. 【学习笔记】ABAP OOD设计模式 - 单例模式

    ABAP OOD设计模式 - 单例模式 整理转自-<SAP ABAP 面向对象程序设计(原则.模式及实践)> 单例模式(Singleton Pattern)是常用的且较为简单的软件设计模式 ...

  8. Go 语言实现 23 种设计模式 单例模式

    Go 语言实现 23 种设计模式 单例模式 单例模式 单例模式是一种常用的软件设计模式,在使用过程中,单例对象的类只有一个实例.使用单例模式,1 可以节省内存等资源,例如windows操作系统的资源管 ...

  9. java singleton inner class_Java面向对象设计模式-单例模式

    Java面向对象设计模式-单例模式 2020-05-28 589 0 单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点,有多重实现方式. 一.饿汉式单例模式,构造方法私有化,在加载类Sin ...

最新文章

  1. 典型用户描述及进一步需求分析
  2. android dialog加载中动画效果
  3. centos7搭建Linux集群,CentOS 7下Kafka集群安装
  4. Python面试题(第二篇)
  5. 【Infragistics教程】在javascript构造函数中创建基本继承
  6. android手机连接PC后怎样切换为U 盘模式
  7. Python - SimpleHTTPServer and CGIHTTPServer
  8. Asp.net 2.0 自定义控件开发[实现自动计算功能(AutoComputeControl)][示例代码下载][续]...
  9. C++11nullptr
  10. DB2 亲身实例(GUI界面) 加 笔记和注意事项
  11. vue 组件创建与销毁
  12. iocomp入门教程(绘制Plot)
  13. 时间管理工具推荐,助你实现高效能,慢生活
  14. 游戏测试的概念是什么?测试方法和流程有哪些?
  15. 发送速率(传输速率)和传播速率
  16. Win10下WinRAR“拒绝访问”解决+获取everyone权限
  17. linux安全审计和加固工具-lynis
  18. cloudreve 开源私有网盘(带离线下载)
  19. gb 28181的20位编码简介
  20. java jtextarea 超出_java – 如何保持JTextArea的大小不变?

热门文章

  1. T82 微信电脑登录手机静音问题
  2. 使用ajax前必须了解的知识
  3. ISO格式云主机创建QCOW2格式镜像
  4. 数据仓库面试题集锦(附答案和数仓知识体系)
  5. v4l2摄像头驱动笔记
  6. iOS 12测评:一改iOS 11华而不实 流畅度大幅提升限制屏幕时间防沉迷
  7. 百度云盘创建共享相册-可以支持多人共同上传照片 的方法【拯救毕业季大家无法及时共享照片的问题】
  8. BeanUtils与BeanCopier的区别
  9. gin框架长连接_[Golang] Gin框架学习笔记
  10. javascript中bind函数理解