Java设计模式(一) 之 详解单例模式

1.前言

单例模式可能是设计模式中相对比较简单的而且在工作中应用最频繁的设计模式了,例如系统配置文件的读取工具类要求得保证其实例唯一性。再比如在需要调用计算机底层时,需要一个Java来使用JNI来与其他语言进行交互,此时可能需要保证Java类的实例是唯一的。

那么在编写单例模式时,需要考虑哪些问题呢?

2.简单实现:

常规单例模式实现的原则:

1.实例变量私有化;

2.构造方法私有化;

3.提供静态的基于类的方法放回实例;

遵循这三个原则,可以在最单纯的环境下设计出单例模式。单例模式的最简单实现就是懒汉式和饿汉式,如下:

饿汉式:

public class SingleTon {

  public static SingleTon instance = new SingleTon();

  private SingleTon(){}

  public static SingleTon getInstance(){
    return instance;
  }
}

特点:线程安全,在类加载初期即完成了对类的实例化;

懒汉式:

public class SingleTon {

  public static SingleTon instance = null;

  private SingleTon(){}

  public static SingleTon getInstance(){
    if(null == instance)
      instance = new SingleTon();
    return instance;
  }

特点:线程不安全,在首次获取实例时完成对类的实例化;

3.双重加锁:

当然,在进行单例模式的设计时,也需要考虑并发的问题,比如饿汉式的设计,如上简单时,并发情况下就会存在问题,可能会产生多个实例;

双重加锁机制:

public class SingleTon {

  public static SingleTon instance = null;

  // .. 内部定义对象锁,当并发条件下,需要竞争syncLock的锁。
  private static final Object syncLock = new Object();

  private SingleTon(){}

  public static SingleTon getInstance(){
    if(null == instance){
        // .. 竞争syncLock锁的线程才可以执行代码块内容,其他线程等待
      synchronized (syncLock) {
        if (null == instance) {
            instance = new SingleTon();
        }
      }
     }
    return instance;
  }

特点:可以防止在多线程环境由于并发导致的多个实例的问题;

4.enum枚举实现单例:

当然即使使用了以上何种方式,在反射和字节码技术面前,还是会毫无抵抗之力,依然可以轻松的生产出多个实例。在JDK1.5中引入了enum枚举类型,依靠枚举类型亦可以实现单利模式,而且可以解决并发和发射层面导致的多个实例的问题。

enum单例实现:

public enum SingleTon {
  insatnce;

  private SingleTon(){}
}

特点:基于enum实现的单例模式,完全可以防止反射的多实例化。

总结:无论何种单例模式的实现,目的都是一样的,在运行环境内产生唯一的实例。但是具体采用哪种单例模式的实现,需要根据场景具体而定。

本人强烈推荐enum实现单例模式,因为enum防止了各种层面对于类的实例化。当然,如果确定运行环境是单线程,那么完全可以使用最简单的饿汉式或者懒汉式实现,因场景而定。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 01:40:35

Java设计模式(一) 之 详解单例模式的相关文章

《Java网络编程核心技术详解》赶稿中......

<精通JPA与Hibernate:Java对象持久化技术详解>这本书写完,就开始着手写<Java网络编程核心技术详解>一书,已经写了一大半,内容包括:Java网络编程的基础知识. 套接字编程.非阻塞通信.创建HTTP服务器与客户程序.数据报通信.对象的序列化与反序列化.Java反射机制.RMI框架.JDBC API.JavaMail API.MVC设计模式.XML处理.安全网络通信.CORBA和Web服务. 每写一章,都会遇到一些挑战,主要是在调试程序时,没有出现预期的结果.例如分

好消息:《Java网络编程核心技术详解》出版

2019年5月从美国回到上海,由于一切都不安定,先在旅馆里宅了4个多月,写完<精通JPA与Hibernate:Java对象持久化技术详解>,就开始写这本书.现在,正是新冠病毒疫情还没结束之际,本书克服种种困难,如期和读者见面了. 我们一不小心,就会被一种潜在的观念暗示:只要忙过了这一阵,将来就能过上高枕无忧的生活.实际上,生活中总是有各种意外的事情发生,小到个人家庭的琐事,大到国家社会的暂时的不安定.为了能随遇而安,就得常常給自己洗脑,不要以为忙过了这一阵,就会有永远太平安宁的出头之日. 戒骄

Java虚拟机工作原理详解

原文地址:http://blog.csdn.net/bingduanlbd/article/details/8363734 一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘当中.然后你在命令行中输入 [java] view plaincopy javac YourClassName.java 此时,你的java代码就被编译成字节码(.class).如果你是在Eclipse IDE或者其他开发工具中,你保存代码

Java的位运算符详解实例

Java的位运算符详解实例——与(&).非(~).或(|).异或(^).右移(>>).左移(<<).无符号右移(>>>) 位运算符主要针对二进制, 它包括了:“与”.“非”.“或”.“异或”."右移"."左移"."无符号右移". 从表面上看似乎有点像逻辑运算符, 但逻辑运算符是针对两个关系运算符来进行逻辑运算, 而位运算符主要针对两个二进制数的位进行逻辑运算. 下面详细介绍每个位运算符. 1.与运

java中static作用详解

static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享. 只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们.因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象. 用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类

Java Service Wrapper配置详解

1 #encoding=UTF-8 2 # Configuration files must begin with a line specifying the encoding 3 # of the the file. 4 5 #******************************************************************** 6 # Wrapper License Properties (Ignored by Community Edition) 7 #*

java classLoader体系结构使用详解

原创整理不易,转载请注明出处:java classLoader体系结构使用详解 代码下载地址:http://www.zuidaima.com/share/1774052029516800.htm jvm classLoader architecture: Bootstrap ClassLoader/启动类加载器 主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作. Extension ClassLoader/扩展类加载器  主要负

java.util.Scanner应用详解++扫描控制台输入

java.util.Scanner应用详解 java.util.Scanner是Java5的新特征,主要功能是简化文本扫描.这个类最实用的地方表现在获取控制台输入,其他的功能都很鸡肋,尽管Java API文档中列举了大量的API方法,但是都不怎么地. 一.扫描控制台输入 这个例子是常常会用到,但是如果没有Scanner,你写写就知道多难受了. 当通过new Scanner(System.in)创建一个Scanner,控制台会一直等待输入,直到敲回车键结束,把所输入的内容传给Scanner,作为扫

Java连接SQLite数据库详解【转】

1 package com.hedalixin; 2 import java.sql.Connection; 3 import java.sql.DriverManager; 4 import java.sql.ResultSet; 5 import java.sql.Statement; 6 7 /** 8 * @author Chrome 9 * 10 */ 11 public class JavaSqlite { 12 13 /** 14 * @param args 15 */ 16 pu