模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式.
懒汉式(线程安全,调用效率不高.但是,可以延时加载)
其他 :
双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
静态内部类式(线程安全,调用效率高.但是,可以延时加载)
枚举单例(线程安全,调用效率高,不能延时加载)
具体实现:
package cn.demo;
/**
* 饿汉式单例模式
* @author Miao
*
*/
public class SingletonDemo1 {
//类加载时就创建对象
private static final SingletonDemo1 INSTANCE = new SingletonDemo1();
//构造器私有化
private SingletonDemo1(){
}
//方法不同步,执行效率高,不支持延时加载
public static SingletonDemo1 getInstance(){
return INSTANCE;
}
}
package cn.demo;
/**
* 懒汉式单例模式
* @author Miao
*
*/
public class SingletonDemo2 {
//类加载时不创建对象
private static SingletonDemo2 instance;
//构造器私有化
private SingletonDemo2 (){
}
//方法同步,执行效率不高,支持延时加载
public static synchronized SingletonDemo2 getInstance(){
if(instance == null) {
instance = new SingletonDemo2();
}
return instance;
}
}
package cn.demo;
/**
* 静态内部类实现单例模式
* @author Miao
*
*/
public class SingletonDemo3 {
//静态内部类,类加载时不创建单例对象
private static class SingletonInnerClass {
private static final SingletonDemo3 INSTANCE = new SingletonDemo3();
}
//构造器私有化
private SingletonDemo3(){
}
//方法不同步,执行效率高,支持延时加载
public static SingletonDemo3 getInstance(){
return SingletonInnerClass.INSTANCE;
}
}
package cn.demo;
/**
* 枚举类型单例模式
* @author Miao
*
*/
public enum SingletonDemo4 {
INSTANCE; //枚举类型都是单例模式
public void operation(){
//do something ...
}
}
package cn.demo;
/**
* 双重检测锁单例模式
* @author Miao
*
*/
public class SingletonDemo5 {
private static SingletonDemo5 instance = null;
public static SingletonDemo5 getInstance() {
if(instance == null) {
SingletonDemo5 sc;
synchronized (SingletonDemo5.class) {
sc = instance;
if(sc == null) {
synchronized (SingletonDemo5.class) {
if(sc == null) {
sc = new SingletonDemo5();
}
}
instance = sc;
}
}
}
return instance;
}
private SingletonDemo5(){
}
}
其实单例模式也是可以通过反射和序列化进行破解的 , 下面以饿汉式单例模式为例说明如何进行破解 :
饿汉式单例模式 :
package cn.demo;
import java.io.Serializable;
/**
* 饿汉式单例模式
* @author Miao
*
*/
public class SingletonDemo6 implements Serializable{
//类加载时就创建对象
private static final SingletonDemo6 INSTANCE = new SingletonDemo6();
//构造器私有化
private SingletonDemo6(){
}
//方法不同步,执行效率高,不支持延时加载
public static SingletonDemo6 getInstance(){
return INSTANCE;
}
}
破解 :
package cn.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 利用反射或序列化破解单例模式的方法
* @author Miao
*
*/
public class Client {
public static void main(String[] args) throws Exception {
SingletonDemo6 s1 = SingletonDemo6.getInstance();
SingletonDemo6 s2 = SingletonDemo6.getInstance();
System.out.println(s1);
System.out.println(s2);
//利用反射破解单例
// Class clazz = (Class) Class.forName("cn.demo.SingletonDemo6");
// Constructor c = (Constructor) clazz.getDeclaredConstructor(null);
// c.setAccessible(true);
// SingletonDemo6 s3 = c.newInstance();
// SingletonDemo6 s4 = c.newInstance();
//利用反序列化破解单例
File file = new File("e:\\temp\\a.txt");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(s1);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
SingletonDemo6 s3 = (SingletonDemo6) ois.readObject();
ois.close();
System.out.println(s3);
}
}
下面以饿汉式单例模式为例来说一下如何防止利用反射和反序列化破解单例模式 :
package cn.demo;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* 饿汉式单例模式(如何防止反射和反序列化)
* @author Miao
*
*/
public class SingletonDemo6 implements Serializable{
//类加载时就创建对象
private static final SingletonDemo6 INSTANCE = new SingletonDemo6();
//构造器私有化
private SingletonDemo6(){
//防止利用反射创建实例
if(INSTANCE != null) {
throw new RuntimeException();
}
}
//方法不同步,执行效率高,不支持延时加载
public static SingletonDemo6 getInstance(){
return INSTANCE;
}
//反序列化时,如果定义了readResolve()则直接返回此方法指定的对象,而不要单独再创建新对象!
public Object readResolve() throws ObjectStreamException{
return INSTANCE;
}
}