设计模式--单例模式

单例模式是设计模式中使用最为普遍的模式之一。它是一种对象创建模式,用于产生一个对象的实例,可以确保系统中的一个类只产生一个实例对象。在java中可以有2个好处

1.对于频繁使用的对象,可以省去对象创建的时间,节省系统开销。

2.由于new操作的次数减少,所有对系统内存的使用频率也降低了,这将会减少GC的压力。

单利模式的核心就是通过一个接口返回唯一一个对象实例,看下面的代码

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

    private static Singleton instance = new Singleton();

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

从上面的代码可以看出,单例类必须要有一个私有(private)的构造函数,只有这样,才能确保该类不会再系统中被实例化,还有instance成员变量和getIntance()方法必须是静态的(static)。

上面这种比较简单的,这种方式不足之处是无法对instance实例做延迟加载,假如单例创建过程很慢,而instance又是静态的,因此在JVM加载单例类时,单例对象就会被创建,如果这个单例类又需要做别的事情的时候,依然会去初始化这个变量去产生实例,不管有没有使用到它,

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

    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }

    public static void getString() {
        System.out.println("get string");
    }

    public static void main(String[] args) {
//      Singleton.getInstance();
        Singleton.getString();
    }
}

结果显示:

singleton is create
get string

所以这个时候就需要引入延迟加载机制。

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

    private static LazySingleton instance = null;

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

    public static void getString() {
        System.out.println("get string");
    }

    public static void main(String[] args) {
//      Singleton.getInstance();
        LazySingleton.getString();
    }
}

结果显示:

get string

这样就达到了延迟加载的效果,首先instance为null,保证启动时没有 额外的负载,getInstance()会判断单利是否存在,存在则返回,不存在则创建,getInstance()需要时同步的,否则在多线程环境下会出现问题,比如线程1正在创建单例对象,在赋值之前,线程2则可能判断instance为null;所以线程2也会去创建实例对象,从而导致多个实例对象被创建,所以需要加入同步关键词来保证只有一个实例对象被创建。

这种方式虽然实现了延迟加载,但是加入同步,导致效率非常低。

所以还有一种方式:类部类的方式

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

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

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

这种方式避免了线程不安全,延迟加载,效率高。

还有几种方式:双重校验

public class Singleton {

    private static volatile Singleton singleton;

    private Singleton() {}

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

进行了两次if (singleton == null)检查,这样就可以保证线程安全了。这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象。这样的优点:线程安全;延迟加载;效率较高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值