java 单例模式

一、定义及应用

  单例模式,是一种常用的软件设计模式,在使用这个设计模式时,单例对象的类要保证只有一个实例存在。

  许多时候整个系统只需要有一个全局对象,这样有利于我们协调整个系统的行为。比如服务器程序中,服务器程序的配置信息存储在一个文件中,使用一个单例对象同意读取,服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了复杂环境下的配置管理。同样,线程池、连接池也是通过单例模式进行管理。

二、实现

1)、两懒汉方式

java 单例模式
public class Singleton{//非线程安全
  private static Singleton instance;
  private Singleton(){};
  public static Singleton getInstance(){
     if(instance==null){
         instance=new singleton();
   }
     return instance;
  }  
}

public class Singleton{//线程安全
  private static Singleton instance;
  private Singleton(){};
  public static synchronized Singleton getInstance(){
     if(instance==null){
         instance=new singleton();
   }
     return instance;
  }  
}
java 单例模式

2)、饿汉方式

java 单例模式
public class Singleton{
  private static final Singleton instance=new Singleton();
  private Singleton(){};
  public static Singleton getInstance(){
    return instance;
  }
}
java 单例模式

3)、内部类

java 单例模式
public class Singleton{//懒加载 线程安全
  private static class SingletonHolder{
    private static final Singlton instance=new Singleton();
  }
  private Singleton(){};
  public static Singleton getInstance(){
    return SingletonHolder.instance;
  }
}
java 单例模式

4)、枚举

java 单例模式
public enum Singleton{
  INSTANCE;
  //....other function    
}
java 单例模式

  写枚举单例的方式,它可能包含实例变量和实例方法,但是简单来说我什么都没用,需要注意的是如果你使用实例方法,你就需要确保方法的线程安全性,避免它会影响对象的状态。通常情况下枚举里面创建实例是线程安全的,但是其它的方法就需要编程者自己去考虑了。

5)、双校验

java 单例模式
public class Singleton{
  private volatile static Singleton instance;//volatile关键字保证当instance变量被初始
  private Singleton(){};//化Singleton实例后,多个线程正确的处理instance变量
  public Singleton getInstance(){
    if(instance==null){
      synchronize(Singleton.class){
        if(instance == null){
          instance = new Singleton();
        }
      }
    }
    return instance;
  }
}
java 单例模式

三、防止破坏单例模式

1、阻止clone()方法创建单例实例的另一个实例

  1)override clone()方法

java 单例模式
    protected Object clone() throws CloneNotSupportedException{
        throw new CloneNotSupportedException();
    }
java 单例模式

  2)一个是单例类一定要是final的,这样用户就不能继承它了

如果有其他方法可以交流交流!

2、防止反射破坏

java 单例模式
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Singletom {

    private static final Singletom instance=new Singletom();
    private Singletom(){};
    public static Singletom getInstance(){
        return instance;
    }
    
    public static void main(String [] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException{
        Class<Singletom> clazz = Singletom.class;
        Constructor<Singletom> constructor = clazz.getDeclaredConstructor();
        
        constructor.setAccessible(true);
        System.out.println(Singletom.instance == constructor.newInstance());
    }
}
View Code

打印出 false

解决方法:没找到答案 期望交流

3、防止系列化破坏

破坏代码:

java 单例模式
public class Singleton implements Serializable{
    private static final long serialVersionUID = 1L;
    private static final Singleton instance=new Singleton();
    private Singleton(){};
    public static Singleton getInstance(){
        return instance;
    }
    public static void main(String [] args){
     // 支持java.io.Serializable的对象都可以写入流中 ByteArrayOutputStream bos
=new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(Singleton.instance); // 根据字节流生成对象 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); Singleton singleton = (Singleton) ois.readObject(); System.out.println(Singleton.instance == singleton); } }
java 单例模式

解决办法:

java 单例模式
//在类中实现readResovle方法
    private Object readResolve(){
        return instance;
    }
java 单例模式

输出为true

 4、防止不同类装载器破坏

如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。例如一些servlet容器对每个servlet使用完全不同的类装载器,这样的话如果有两个servlet访问一个单例类,它们就都会有各自的实例。

解决办法:

java 单例模式
    private static Class getClass(String classname)throws ClassNotFoundException {     
          ClassLoader classLoader = Thread.currentThread().getContextClassLoader();     
          if(classLoader == null)     
             classLoader = Singleton.class.getClassLoader();     
          return (classLoader.loadClass(classname));     
    }
java 单例模式

参考:http://www.oracle.com/technetwork/articles/java/singleton-1577166.html

 

java 单例模式,布布扣,bubuko.com

java 单例模式

上一篇:JavaScript中七种函数调用方式及对应 this 的含义


下一篇:python之GUI自定义界面设计 2014-4-10