GOF设计模式之单例模式的分类以及破解
2016-10-19 00:45
357 查看
在GOF设计模式中,分为创建型模式,结构性模式以及行为型模式三类。而现在要说到的单例模式就属于创建型模式中的一种。
什么是单例模式?有哪些单例模式?
顾名思义,就是保证一个类只能够创建一个对象,并且对外提供一个访问该实例的方法。这里会设计到五种单例模式,分别为饿汉式,懒汉式,双重检测锁式,静态内部类式以及枚举单例。
饿汉式:
懒汉式:`
枚举单例:
静态内部类的单例模式:
双重检测锁式:
为了防止对对象的创建,我们在使用不同方法的时候总是将构造器进行了私有化。可是,这样就一定能够保证只创建一个对象么,答案是否定的。即使构造器的私有的,在外部我们还是能够创建对象的,这里用到的就是反射。
通过反射来破解单例模式:
即然反射能够破解单例模式,那有没有什么方法不让通过反射创建出对象?下面用到的就是抛出异常的方式防止创建多个对象。
什么是单例模式?有哪些单例模式?
顾名思义,就是保证一个类只能够创建一个对象,并且对外提供一个访问该实例的方法。这里会设计到五种单例模式,分别为饿汉式,懒汉式,双重检测锁式,静态内部类式以及枚举单例。
饿汉式:
/** * 饿汉式单例设计模式 */ public class SingletonDemo01 { //类在初始化的时候立即创建这个对象,不会延时加载,当然也是线程安全的。 private static SingletonDemo01 instance=new SingletonDemo01(); //构造器私有化 private SingletonDemo01(){ } //对外提供公有的静态方法,返回该对象 public static SingletonDemo01 getInstance(){ return instance; } }
懒汉式:`
/** * 懒汉模式的单例设计模式 * 需要用到的时候才去创建 */ public class SingletonDemo02 { private static SingletonDemo02 instance=null; private SingletonDemo02 (){ } //方法整体解锁,线程安全 public static synchronized SingletonDemo02 getInstance(){ //真正要使用的时候才去加载,起到了延时加载的作用 if(instance==null){ instance=new SingletonDemo02(); } return instance; } }
枚举单例:
/** *枚举单例 */ public enum SingletonDemo03 { instance; }
静态内部类的单例模式:
/** *静态内部类的单例模式 */ public class SingletonDemo04 { //静态内部类 private static class SingletClassInstance{ private static final SingletonDemo04 instance=new SingletonDemo04(); } private SingletonDemo04(){ } public static SingletonDemo04 getInstance(){ return SingletClassInstance.instance; } }
双重检测锁式:
/** * 双重检测锁式 */ public class SingletonDemo05{ private static SingletonDemo05 instance = null; private SingletonDemo05(){ } public static SingletonDemo05 getInstance() { if (instance == null) { SingletonDemo05 s; synchronized (SingletonDemo05.class) { s = instance; if (s == null) { synchronized (SingletonDemo05.class) { if(s==null){ s=new SingletonDemo05(); } } instance=s; } } } return instance; } }
为了防止对对象的创建,我们在使用不同方法的时候总是将构造器进行了私有化。可是,这样就一定能够保证只创建一个对象么,答案是否定的。即使构造器的私有的,在外部我们还是能够创建对象的,这里用到的就是反射。
通过反射来破解单例模式:
public class BreakSingleton { public static void main(String[] args) throws Exception { //通过反射获取clazz对象 这里注意要测试类在哪一个包下 Class<SingletonDemo01> clazz=(Class<SingletonDemo01>)Class.forName("com.sg.Singleton.SingletonDemo01"); //获得空的构造器 Constructor<SingletonDemo01> c=clazz.getDeclaredConstructor(null); //设置不进行安全检查 c.setAccessible(true); //通过反射创建对象 SingletonDemo01 s1=c.newInstance(); SingletonDemo01 s2=c.newInstance(); System.out.println(s1==s2); //print false } }
即然反射能够破解单例模式,那有没有什么方法不让通过反射创建出对象?下面用到的就是抛出异常的方式防止创建多个对象。
public class saveSingleton { //类在初始化的时候立即创建这个对象,不会延时加载,当然也是线程安全的。 private static saveSingleton instance=new saveSingleton(); //构造器私有化 private saveSingleton() { if(instance!=null){ throw new RuntimeException(); } } //对外提供公有的静态方法,返回该对象 public static saveSingleton getInstance(){ return instance; } }
相关文章推荐
- GoF设计模式的分类:
- 设计模式分类以及六大原则
- GOF以及java的23种设计模式简介
- GOF设计模式分类
- 设计模式的分类以及6大原则
- GOF以及java的23种设计模式简介
- 设计模式之路--Gof23分类
- 设计模式的说明以及分类
- 设计模式的分类以及六大设计原则
- GOF以及java的23种设计模式简介
- 设计模式——设计模式三大分类以及六大原则
- GOF 23种设计模式 怎么分类
- GoF设计模式的分类极其目的
- GOF以及java的23种设计模式简介
- GOF设计模式-创建型模式理解与思索(一)(Abstract Factory 和Builder)
- GOF设计模式学习小节(二)
- 从GOF的设计模式说起
- GoF 23个经典的设计模式04--创建模式之原型模式(未完代续)
- GoF 23个经典的设计模式6--结构模式之适配器模式(未完代续)
- GoF 23个经典的设计模式03--创建模式之工厂方法(未完代续)