原来转载过一篇关于单例模式的博客
http://blog.csdn.net/u011700281/article/details/21951795
现在自己由于实现一些管理器(比如 mysq了连接的管理器,redis的连接管理器,以及config的连接管理器),经常用到单例模式,不过,公司内的单例模式的实现方法有很多,自己也跟着总结一下。
首先,为什么需要单例模式呢?比如,你需要获得一个mysql连接,你肯定希望所有mysql的连接池是被一个对象管理的,而不希望你从这个对象可以获得连接,从另一个对象也可以获得连接,所以,就很有必要让这个对象唯一。这时候就需要实现单例模式了。
单例的实现,根本上来说,是要让构造函数私有化,因为一旦构造函数暴露,总是可以通过new 来初始化这个对象的。
构造函数私有了,也就是只有本类之内能调用这些方法,所以下面介绍几种实现。
1.最简单的单例
public class Singleton { private final static Singleton instance = new Singleton(); private Singleton(){} // some other code; }这个简单粗暴,直接设置一个静态变量,由于静态变量是类共有的,所有只会被调用一次。
简单粗暴,但是会有一些问题。
第一,这个类在加载的时候就必须创建这个对象,假设创建这个类的代价很高,那在服务启动时候,有很多这样的类的话,就导致速度很慢。
第二,假设这个类的构造函数调用了其他类的静态资源,这些静态变量这时候并没有被加载进来,这就会出现问题。
如果创建对象没什么代价,而且也不会用到其他变量的时候,使用这个方法还是很简单的。
2.延迟创建
private static Singleton instance = null; private Singleton(){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }这个方法,乍一看不错啊,只有当使用的时候才会创建这个对象。而且,这个方法确实不错啊,但是并发情况下这是很渣的。
3.于是看到一种比较狠的,使用了syschonised
public class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance =new Singleton(); } } } return instance; } }
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">在这个方法中调用了同步锁,所以不会有并发问题。</span>
4.使用holder的方法,将管理实例完全封装起来
也就是实现一个内部类
public class Singleton { private Singleton(){} private static class SingletonHolder{ private static Singleton instance = new Singleton(); } }这个内部类对于外界来说完全透明,而且这个私有变量对外部的类来说是可以访问的,由于这个内部类只在使用的时候加载并且创建该实例,也是延迟创建的。
5.使用枚举,枚举天生就是单例,所以很好用的。
6.使用spring托管,这个不用说了。
以上几种方式,各有优缺点把,使用哪个就看需要。
原文:http://blog.csdn.net/u011700281/article/details/43536731