单例模式是在平时的项目开发中比较常见的一种设计模式,使用比较普遍,网上的资料也是一抓一大把,小Alan也来凑凑热闹,为以后充实点设计模式相关的内容做个简单的开篇。

单例模式是一种创建对象的模式,用于产生这个类的一个具体的实例对象,跟普通的对象创建比起来就那么一点点区别,区别就在于它可以确保项目中的一个类只会产生一个具体的对象实例。而不会出现第二个对象实例,第三个对象实例。所有使用到这个对象实例的地方实际上用的都是同一个对象,这就是所谓的单例模式,对于初学者还可能陌生,对于老司机们来讲这可是最最简单的设计模式之一。

在Java中使用单例模式有哪些好处嘞?

①对于频繁使用、经常使用的对象,可以省略创建对象也就是没对象的需要new一个对象所花费的时间,这对于那些重量级的对象来说,还是能少来一个就少来一个,用老对象就好了,减少开销;

②创建对象的次数变少了,对系统内存使用的频率就会降低,这样就减轻了GC的压力,缩短了GC所耗费的时间;

③开发项目的过程中遇到类只需要一个对象实例的时候,那么就是选择这模式无疑了。

单例的实现1:

下面给出一个单例的实现,这个实现是so easy的,代码如下:

 /**
  * 单例模式
  * @author AlanLee
  *
  */
 public class Singleton
 {

     // 饿汉模式
     private static Singleton instance = new Singleton();

     private Singleton()
     {
         System.out.println("Singleton is create");
     }

     public static Singleton getInstance()
     {
         return instance;
     }

 }

使用这种方式创建单例对象有几点需要特别注意。

第一点:我们要保证我们的项目中不会有人意外的创建多余的对象实例的话,我们需要把Singleton的构造函数设置为private私有的。这样其他开发人员就不能随便的创建这个类的对象实例了,从而避免该类的对象实例被错误的创建出来;

第二点:instance对象必须是private私有的并且static静态化的。如果不是private私有的,那么instance的安全性无法得到保证。一不小心可能就被其他开发人员来个Singleton.instance=xxx的,那这个对象也就被改变了,如果=null的话,可想而知,在使用这个对象实例的使用,迎接你的将是空对象异常的怀抱。其次,因为工厂方法getInstance()是static静态方法,因此方法中返回的变量也得是static的。

探讨:每种实现方式在高并发环境下性能如何呢,每种实现方式有木有什么不足之处?

这个单例模式的实现方式性能是非常好的,因为工厂方法getInstance()只是简单的返回instance对象实例,并没有任何锁操作,因此在并行程序中,还是会有比较不错的表现滴。

但是这种方式有一点不足,就是instance对象实例在什么时候被创建出来是不受控制的,基础好点的都知道static成员会在类第一次初始化的时候被创建,这个时候可不一定是工厂方法getInstance()第一次被调用的时候。

假设你的单例模式是这样的,代码如下:

 /**
  * 单例模式:实例对象第一次初始化的问题
  *
  * @author AlanLee
  *
  */
 public class Singleton2
 {
     public static int STATUS = 1;

     private static Singleton2 instance = new Singleton2();

     private Singleton2()
     {
         System.out.println("Singleton2 is create");
     }

     public static Singleton2 getInstance()
     {
         return instance;
     }

 }

注意,这个单例还包含另一个静态成员STATUS。此时,在任何地方引用这个STATUS都会导致instance对象实例被创建(任何对Singleton2方法或者字段的引用,都会导致类初始化,并创建instance实例,但是类初始化只有一次,因此instance实例永远只会被创建一次)。

比如:System.out.println(Singleton.STATUS);

上述println会打印出:

可以看到,就算我们没有要求创建instance单例对象,new Singleton2()也会被调用。

如果不在乎这个小小的不足之处,这种单例模式的实现方式是一种不错的选择。它容易实现,代码易读而且性能优越。

单例的实现2:

如果你想精准的控制instance的创建时间,那么就需要使用下面这种方式,一种支持延迟加载的策略,它只会在instance被第一次使用时才会创建对象。代码如下:

 /**
  * 单例模式之懒汉模式
  *
  * @author AlanLee
  *
  */
 public class LazySingleton
 {
     private static LazySingleton instance = null;

     private LazySingleton()
     {
         System.out.println("LazySingleton is create");
     }

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

最初我们并不需要实例化instance对象实例,只有工厂方法getInstance()被第一次调用时才会创建单例对象。但是在高并发环境下,为了防止对象被对此创建,我们不得不使用synchronized进行方法同步。这种实现的好处是,充分利用了延迟加载,只有在真正需要时才创建对象。但坏处也很明显,并发环境下加锁,在锁竞争激烈的时候会对性能产生一定的影响。

此外,还有一种被称为双重检查模式的方法可以用于创建单例。这是一种非常丑陋、复杂的方法,甚至在低版本的JDK中都不能保证正确性。不推荐使用,也没必要在这种方法上花费太多时间。

单例的实现3:

在上述的单例模式实现方式中,可说是各有千秋,那么第三种方式便是结合两者的优势的一种两全其美的实现方式,代码如下:

 /**
  * 无懈可击之单例模式
  *
  * @author Alanlee
  *
  */
 public class StaticSingleton
 {

     private StaticSingleton()
     {
         System.out.println("StaticSingleton is create");
     }

     private static class SingletonHolder
     {
         private static StaticSingleton instance = new StaticSingleton();
     }

     public static StaticSingleton getInstance()
     {
         return SingletonHolder.instance;
     }

 }

上述代码实现了一个单例模式,并且同时拥有前两种方式的优点。首先工厂方法getInstance()没有使用同步锁,这使得在高并发环境下性能得到了提升。其次,只有在工厂方法getInstance()被第一次调用时,StaticSingleton的实例才会被创建。这种方式巧妙地使用了内部类和类的初始化方式。内部类SingletonHolder被申明为private私有的,这使得我们不可能在外部访问并初始化它。而我们只能在工厂方法getInstance()内部对SingletonHolder类进行初始化,利用虚拟机的类初始化机制创建单例对象。

结束语:宠辱不惊,闲看庭前花开花落;去留无意,漫随天外云卷云舒......小Alan除了喜欢看技术书籍,还是一个武侠玄幻小说爱好者呢!希望自己在IT的这条道路上就能像小说中的主人公一样,纵然困难重重,亦能化险为夷成就康庄大道,至于坐拥美女环抱啥的,小Alan可不想啊,还是有一个深爱的女人足以。

可爱博主:AlanLee

博客地址:http://www.cnblogs.com/AlanLee

本文出自博客园,欢迎大家加入博客园。

Java设计模式探讨之单例模式的更多相关文章

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

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

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

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

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

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

  4. 重学 Java 设计模式:实战单例模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 5个创建型模式的最后一个 在设计模式中按照不同的处理方式共包含三大类:创建型模式.结 ...

  5. Java设计模式4:单例模式

    前言 非常重要,单例模式是各个Java项目中必不可少的一种设计模式.本文的关注点将重点放在单例模式的写法以及每种写法的线程安全性上.所谓"线程安全性"的意思就是保证在创建单例对象的 ...

  6. 10.Java设计模式 工厂模式,单例模式

    Java 之工厂方法和抽象工厂模式 1. 概念 工厂方法:一抽象产品类派生出多个具体产品类:一抽象工厂类派生出多个具体工厂类:每个具体工厂类只能创建一个具体产品类的实例. 即定义一个创建对象的接口(即 ...

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

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

  8. 【java设计模式】-04单例模式

    单例模式 定义: 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 类型: 创建类模式 类图: 单例模式特点 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单 ...

  9. Java设计模式09:单例模式的强化(控制实例个数n)

    1. 单例模式的本质: 控制实例数目(目的节约资源) 2. 单例模式体现的一些思想: (1)延迟装载(Lazy Load):懒汉式 (2)缓存:饿汉式 3. 单例模式的变形使用: 控制使用实例个数为3 ...

随机推荐

  1. 14.LINUX-platform机制实现驱动层分离(详解)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 本节目标:        学习platform机制,如何实现驱动层分离 1.先来看看我们之前分析输入子系统的分层概念,如下图所示: 如上图所示,分 ...

  2. WebSocket部署服务器外网无法连接解决方案

    首先要说的是我遇见的问题: WebSocket connection to 'ws://www.xxxx.com/xxx/xx' failed: Error during WebSocket hand ...

  3. [js高手之路] html5 canvas系列教程 - 图片操作(drawImage,clip,createPattern)

    接着上文[js高手之路] html5 canvas系列教程 - 文本样式(strokeText,fillText,measureText,textAlign,textBaseline)继续,本文介绍的 ...

  4. TCP/IP(二)物理层详解

    前言 在前面说了一下,计算机网络的大概内容,没有去深刻的去了解它,这篇文章给大家分享一下物理层! 我们知道ISO模型是七层,TCP/IP模型是五层,而tcp/ip协议只将七层概括为4层,我们将学习其中 ...

  5. 【转】Keberos认证原理

    前几天在给人解释Windows是如何通过Kerberos进行Authentication的时候,讲了半天也别把那位老兄讲明白,还差点把自己给绕进去.后来想想原因有以下两点:对于一个没有完全不了解Ker ...

  6. CentOS7 Redis安装

    Redis介绍 1.安装Redis 官方下载地址:http://download.redis.io 使用Linux下载:wget http://download.redis.io/redis-stab ...

  7. 【转】 中兴OLT-C300常用命令

    中兴OLT C300show running-config (加载各种板卡)show gpon onu uncfg (查看OLT所有未配置的ONU)show gpon onu uncfg gpon-o ...

  8. python 发送邮件,未完

    def send_mail(): try: print "send mail..." # handle = smtplib.SMTP('smtp.163.com', 25) # h ...

  9. 【完美解决】2017打开MVC 4项目,cshtml页面提示‘当前上下文不存在名称model’

    时间:2017/10/19 背景:领导让再之前的MVC 4老项目上新增功能,从GIT上拉取下来,使用VS2017打开之后,cshtml界面所有和Razor相关的代码均被提示‘当前上下文不存在名称XXX ...

  10. JS代码中!!的用法,以及代码性能对比

    一.!!的理解 解释: !!的意思就是把一个任意类型的值转换为布尔类型的值,一个!是取非 再一个!又取非,相当于把这个数据转换为boolen类型了. 使用场景: 常常用在if(a).if(!!a)这样 ...