您的位置:首页 > 编程语言 > Go语言

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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息