设计模式之单例模式
2017-01-09 18:32
211 查看
1.单例模式
即保证整个系统只有一个实例对象1.1使用场景可有:
1).数据缓存对象
2).工具方法1.2实现方式:
通过对构造函数私有化类实现对象单例2.单例的代码实现
2.1实现方式一
(懒汉式)
Singletonpublic class Singleton { private static Singleton _instance = null; private Singleton(){ System.out.println("初始化"); } public static Singleton getInstance(){ if(_instance == null){ _instance = new Singleton(); } return _instance; } public static void doSomething(){ System.out.println("做点东西吧!"); } }Client
public class Client{ public static void main(){ Singleton singleton = Singleton.getInstance(); singleton.doSomething(); System.out.println(singleton); singleton = Singleton.getInstance(); System.out.println(singleton); } }上面这种方式存在问题,当有多线程时,会导致实例被创建多次。于是我们引入同步锁:
2.2同步锁优化
Singletonpublic class Singleton{ private static Singleton _instance = null; private Singleton(){} public static Singleton getInstance(){ synchronized(Singleton.class){ if(_instance == null){ _instance = new Singleton(); } return _instance; } } public static void doSomething(){ System.out.println("做点东西吧"); } }Client:
public class Client{ public static void main(String[] args){ for(int i = 0;i < 10;i++){ Thread t = new Thread(new Runable(){ public void run(){ Singleton singleton = Singleton.getInstnace(); System.out.println(singleton); } }); t.start(); } } }
如上,加入同步关键字后会引发效率问题,我们可以加入双检锁,缩小锁的范围
2.3使用双检锁
Singletonpublic class Singleton { private static Singleton _instance = null; private Singleton() { } /** * new Singleton() 这句话其实是包含三个逻辑 1.给Singleton实例创建空间 2.初始化Singleton的构造器 * 3.把Singleton这个实例的引用赋值给_instance (_instance就不为null了) * 由于jvm运行期的优化,第二部和第三步的顺序是不能保证的 这样就会导致出现两种情况1,2,3或1,3,2 */ public static Singleton getInstance() { if (_instance == null) { synchronized (Singleton.class) { if (_instance == null) { _instance = new Singleton(); } } } return _instance; } public static void doSomething() { System.out.println("做点东西吧"); } }
Client
public class Client{ public static void main(String[] args){ for(int i = 0;i < 10;i++){ Thread t = new Thread(new Runnable(){ public void run(){ Singleton singleton = Singleton.getInstance(); System.out.println(singleton); } }); t.start(); } } }如上这种实现方式中 new Singleton()包含三个逻辑:
1.给Singleton实例创建空间
2.初始化Singleton的构造器
3.把singleton这个实例的引用赋值给_instance (_instance就不为null了)
假如第一个线程调用获取实例的方法时,执行到new Singleton();这句话,只执行了1,3两个步骤,
这个时候_instance已经不为null了,但是构造器没有初始化完成,然后第二个线程进来,由于此时
_instance已经不为null了,所以在判读非空的时候就直接返回了,这时如果线程2使用这个构造器没
有初始化完成的singleton对象的话,就会报错!
解决方案有:
1.jdk1.5及1.5以后版本可以在变量中声明volatile关键字,让线程强制读取主内容中的变量,而不去读取变量副本。
2.通过饿汉式的单例模式来解决
3.使用静态类来保存instance
2.4使用volatile关键字
Singletonpublic class Singleton { private static volatile Singleton _instance = null; private Singleton(){} public static Singleton getInstance(){ if(_instance == null){ synchronized(Singleton.class){ if(_instance == null){ _instance = new Singleton(); } } } return _instance; } public static void doSomething(){ System.out.println("做点东西吧!"); } }
2.5饿汉式
public class Singleton{ private final static Singleton _instance = new Singleton(); private Singleton(){ System.out.println("初始化!"); } public static Singleton getInstance(){ return _instance; } public static void doSomething(){ System.out.println("做点东西吧!"); } }
Client
public class Client { public static void main(String[] args) throws ClassNotFoundException { Class.forName("singleton.Singleton"); Singleton.getInstance().doSomething(); } }
2.6静态类保存instance的方式
Singletonpublic class Singleton{ private static class SingletonHolder{ static Singleton _instance = new Singleton(); } private Singleton(){ System.out.println("初始化!"); } public static Singleton getInstance(){ return SingletonHolder._instance; } public static void doSomething(){ System.out.println("做点什么吧!"); } }
Client
public class Client { public static void main(String[] args) throws ClassNotFoundException { Class.forName("singleton.Singleton"); Singleton.getInstance().doSomething(); } }
小结:在软件设计当中,我们应该遵循一个法则,简单,正确。不为了炫耀技术来实现需求,只有简单,正确的实现方式,它生命周期才是最长,因它可维护性高。所以选择懒汉还是饥汉的方式是根据具体的场景定的。
相关文章推荐
- 闲聊设计模式和类
- 好书整理系列之-设计模式:可复用面向对象软件的基础 5
- 好书整理系列之-设计模式:可复用面向对象软件的基础 4
- 好书整理系列之-设计模式:可复用面向对象软件的基础 3
- 好书整理系列之-设计模式:可复用面向对象软件的基础 2
- 好书系列之-设计模式:可复用面向对象软件的基础 1
- 好书整理系列之-设计模式:可复用面向对象软件的基础 5.5
- 设计模式、用Delphi描述-->Abstract Factory模式
- 设计模式、用Delphi描述-->Factory Method模式
- 设计模式、用Delphi实现---->Strategy模式
- 与大虾对话: 领悟设计模式
- 好书整理系列之-设计模式:可复用面向对象软件的基础 6
- 设计模式入门(1)------单件(Singleton)
- 设计模式、用Delphi描述-->Reference Count pattern
- Engine-Collection-Class,一种用来建立可重用企业组件的设计模式
- 好书整理系列之-设计模式:可复用面向对象软件的基础 7
- 好书整理系列之-设计模式:可复用面向对象软件的基础 8
- Jive 中的设计模式
- 设计模式、用Delphi描述-->Visitor模式
- 设计模式、用Delphi实现---->Template Method模式