设计模式随笔-单件模式

来源:互联网 发布:手机看网络电视流量 编辑:程序博客网 时间:2024/06/05 06:00

单件模式

单件模式是可以用来创建独一无二的,只能有一个的对象。
单件模式的类图可以说是最简单的,事实上它的类图只有一个类,但是也不要把它想的那么简单,因为它也是需要很多限制才能够安全的运行起来。

首先我们来看一个经典的单件模式的代码:

public class Singleton {    private static Singleton singleton;    private Singleton(){    }    public static Singleton getInstance(){        if (singleton == null){            return new Singleton();        }        return singleton;    }    //其他方法}

构造器设置为私有的,这样只能类的内部创建对象了。外部需要得到该对象的话,就必须调用getInstance方法来获取,而getInstance里面判断了如果singleton对象为空则创建这个对象,否则返回该对象,这样就创造了单件的对象了。

单件模式与之间命名一个静态对象相比有一个优点,就是能够延迟实例化。不会在项目加载的时候就实例化了对象。

单件模式:确保一个类只有一个实例,并提供一个全局访问点。

简单单件模式的缺点

但是对于简单的单件模式,在多线程的情况下,并不适用的。如下图是两个线程同时请求单件对象:
多线程单件模式
这样就有两个单件对象了。这可能会让系统存在无法发现的问题,怎么查也查不到。
解决方法,使用同步代码块:

public class Singleton {    private static Singleton singleton;    private Singleton(){}    public static synchronized Singleton getInstance(){        if (singleton == null){            return new Singleton();        }        return singleton;    }    //其他方法}

但是使用同步代码块的话,就会造成性能上的问题,这就引申出了另外一个问题了。而且单件模式的这个代码块,只是在创建对象的时候有用,之后每次调用都成为了累赘了。

能够改善多线程吗?
1.如果getInstance的性能对程序不是关键的,那么就什么都不用管。
对于不是程序的关键,使用同步代码块,既简单又有效。但是可能会造成效率下降100倍。

2.急切的初始化对象,而不用懒加载的方法。
如果程序总是使用单件,并且程序在启动时负担不重,可以考虑使用立即初始化单件对象。

public class Singleton {    private static Singleton singleton = new Singleton();    private Singleton(){}    public static synchronized Singleton getInstance(){        return singleton;    }    //其他方法}

这个方法依赖了JVM加载这个类时就创建了一个单件对象。JVM保证在任何线程访问之前就创建好了对象。

3.用“双重检查加锁”在getInstance()中减少同步的使用。

public class Singleton {    //volatile 只适用于java5以上的版本哦,volatile能保证对象被初始化完成之后能够正确处理多线程    private volatile static Singleton singleton;    private Singleton(){}    public static Singleton getInstance(){        if (singleton == null){            synchronized (Singleton.class) {                if (singleton == null) {                    return new Singleton();                }            }        }        return singleton;    }    //其他方法}

如果性能是你关注的,那么使用这种方法会大大减少getInstance的时间消耗。

总结

有些对象我们只需要一个,比方说:线程池、缓存、对话框、注册表等等。这时候不妨使用单件模式来实现。

单件模式:确保一个类只有一个实例,并提供一个全局访问点。

0 0
原创粉丝点击