单例设计模式

一、单例:

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

在java语言中,单例带来了两大好处:

1.对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级的对象而言,是非常可观的一笔系统开销。
2.由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间。 所以对于系统的关键组件和被频繁操作的对象,使用单例模式便可以有效地改善系统性能。 单例的参与者非常简单,只有单例类和使用者两个

单例模式三要点:

(1)、单例类只能有一个实例 这是最基本的,真正做到整个系统中唯一并不容易,通常还要考虑反射破坏、序列化/反序列化、对象垃圾回收等问题。
(2)、单例类必须自己创建自己的唯一实例 通常给实例构造函数protected或private权限。
(3)、单例类必须给所有其他对象提供这一实例 通常定义静态方法getInstance()返回。

优点:

(1)、提供了对唯一实例的受控访问,避免对资源的多重占用。

(2)、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。

(3)缩小名空间,避免全局变量污染空间,但比类操作更灵活。

缺点:

(1)、由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。

(2)、 单例类的职责过重,在一定程度上违背了”单一职责原则”。

因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
二、实现方式
1、饿汉式(简单可用)
Lazy 初始化:否;多线程安全:是;
优点:没有加锁,执行效率会提高。
缺点:没有Lazy初始化,可能有时候不需要使用,浪费内存。

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton (){}

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

2、懒汉式(线程不安全,不可用)
Lazy 初始化:是;多线程安全:否;
能够在getInstance()时再创建对象,所以称为懒汉式。这种实现最大的问题就是不支持多线程。因为没有加锁同步。

public class Singleton {
    private static Singleton instance;

    private Singleton (){}

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

3、同步方法的懒汉式(同步方法效率低,不推荐)
Lazy 初始化:是;多线程安全:是;
除第一次使用,后面getInstance()不需要同步;每次同步,效率很低。

public class Singleton {

    private static Singleton instance;
    private Singleton (){}

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

4、双重校验锁(可用)
Lazy 初始化:是;多线程安全:是;
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。实例变量需要加volatile 关键字保证易变可见性,JDK1.5起才可用。

public class Singleton implements Serializable{

    private volatile static Singleton singleton;

    private Singleton() {
      if (null != Singleton.singleton) {
          throw new RuntimeException();
      }
    }

    private Object readResolve() {
        return Singleton.singleton;
    }

    public static Singleton getSingleton() {
         if (singleton == null) {
             synchronized (Singleton.class) {
                 if (singleton == null) {
                     singleton = new Singleton();
                  }
             }
         }
         return singleton;
    }
}

5、静态内部类(推荐)
Lazy 初始化:是;多线程安全:是;
同样利用了JVM类加载机制来保证初始化实例对象时只有一个线程,静态内部类SingletonHolder 类只有第一次调用 getInstance 方法时,才会装载从而实例化对象。

public class Singleton {

    private static class SingletonHolder {

       private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton (){}

    public static final Singleton getInstance() {

        return SingletonHolder.INSTANCE;
    }
} 

6、枚举(《Effective Java》推荐,不常见)
Lazy 初始化:是;多线程安全:是;
从Java1.5开始支持enum特性;无偿提供序列化机制,绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候。不过,用这种方式写不免让人感觉生疏,这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。

public enum Singleton {

    //定义一个枚举的元素,就代表Singleton实例
    INSTANCE;

    /*
    **假如还定义有下面的方法,调用:Singleton.INSTANCE.doSomethingMethod();
    */
    public void doSomethingMethod() {

    }
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值