《JAVA设计模式》之单例模式

一.单例模式简介

单例:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自动实例化并向整个系统提供这个实例。这个类称为单例类。

单例模式的结构:

  • 单例类只能有一个实例
  • 单例类必须自己创建自己的唯一实例
  • 例类必须给所有其他对象提供这一实例

二.饿汉式单例

/*
 * 饥饿式单例类
 */
public class SingletionDemo1 {

         private static SingletionDemo1 instance=new SingletionDemo1();

         /**
         * 私有构造
         */
        private SingletionDemo1() {

        }

        /*
         * 静态工厂方法
         */     
        public static SingletionDemo1 getInstance() {
            return instance;
        }
}

上面的例子中,在这个类被加载时,静态变量instance会被初始化,此时类的私有构造子会被调用。这时候,单例类的唯一实例就被创建出来了
饿汉式其实是一种比较形象的称谓,既然饿,那么在创建对象实例的时候就比较着急,饿了嘛,于是在装载类的时间就创建实例

private static SingletionDemo1 instance=new SingletionDemo1();

饿汉式是典型的空间换时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间

变种饿汉式

public class Singleton {
         private static Singleton instance;

         static {
             instance=new Singleton();
         }

         public Singleton() {
            // TODO Auto-generated constructor stub
        }
         public static Singleton getInstance() {
             return instance;
         }
}

三.懒汉式单例

/*
 * 饿汉式单例类
 */
public class SingletionDemo2 {

              private static SingletionDemo2 instance=null;


              /*
               * 私有默认构造子
               */
            private SingletionDemo2() {

            }

            /*
             * 静态工厂方法
             */
            public static synchronized SingletionDemo2 getInstance() {
                    if(instance==null) {
                         instance=new SingletionDemo2();
                    }
                    return instance;
            }
}
  • 上面的懒汉式单例类实现里对静态工厂方法使用了同步化,以处理多线程环境
  • 懒汉式其实是一种比较形象的称谓,既然懒,那么在创建对象实例的时候就不着急。会一直等到马上要使用对象实例的时候才会创建,懒人嘛,总是推脱不开的时候才会真正去执行工作,因此在装载对象的时候不创建对象实例
private static SingletionDemo2 instance=null;
  • 懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间
  • 由于懒汉式的实现是线程安全的,这样会降低整个访问的速度,而且每次都要判断。那么有没有更好的方式实现呢?

四.双重检查锁

双重检查锁可以实现线程安全,又能够使性能不受很大的影响。或许有很多人想问为什么用使用双重检查锁。其实这个需要解释一下了。

比如现在有两个线程来访问,都访问到了第一个if(instance==null)后面了,但因为后面是同步块,只能一个线程进入,另一个等待在同步块,访问后实例化了一个对象,退出同步块后,另一个等待的线程进入同步代码块,但因为instance已经被实例化了,所以直接退出同步代码块,直接返回instance
在JDK1.5之后,双重检查锁定才能够正常达到单例效果。

public class Singleton {
         private volatile static Singleton instance=null;
         public Singleton() {

        }

         public Singleton getInstance() {
             //先检查对象是否存在,如果不存在才进入下面的同步块
              if(instance==null) {
                  //同步块,线程安全的创建
                 synchronized(Singleton.class) {
                     //若实例还是为空,那就创建
                     if(instance==null) {
                         instance=new Singleton();
                     }
                 }
              }
                return instance;
         }
}

五.静态内部类

public class Singleton {//这个不同于饿汉式的,在类的加载中,对象就会被实例化,只要调用getInstance方法才会加载类SingletonHandler,让instance对象实例化,这种方式实现了线程安全,在一定程度上也可以有很好的性能。
          private static class SingletonHandler{
              private  static final Singleton instance=new Singleton();
          }
          private Singleton() {
            // TODO Auto-generated constructor stub
        }
          public  static final Singleton getInstance() {
                 return SingletonHandler.instance;
          }
}

六.枚举

public enum Singleton {
          //Singleton的一个实例
          instance;
          //功能的操作
    public void waterSingleton() {

    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值