设计模式(三)Singleton Pattern单例设计模式

1.饿汉式

public class SingletonDemo {
    private static SingletonDemo s=new SingletonDemo();
    private SingletonDemo() {}
    public static SingletonDemo getInstance() {
            return s;
    }
}
public class Test {
    public static void main(String[] args) {
        SingletonDemo s=SingletonDemo.getInstance();
    }
}

步骤:    1.new出静态对象

    2.构造方法私有化

    3.写一个方法返回静态对象

说明:   1.由于加载类时天然的是线程安全

    2.方法没有同步,调用效率高

    3.立即加载,没有延时加载的优势

2.懒汉式(延时加载)

public class SingletonDemo {
    private static SingletonDemo s;
    private SingletonDemo() {}
    public static synchronized SingletonDemo getInstance() {
            if(s==null) s=new SingletonDemo();
            return s;
    }
}
public class Test {
    public static void main(String[] args) {
        SingletonDemo s=SingletonDemo.getInstance();
    }
}

优势:   1.修改点同步,在线程高并发时,能够保证安全性

    2.延时new出类,能够做到用的时候去new它

3.双重检测锁实现

由于java编译器优化的原因和JVM底层内部模型的原因,偶尔会出一点问题,不建议使用

这个模式将同步内容下方到if内部,提高了执行效率,不必每次获取对象时都进行同步,至于一次才同步

public class SingletonDemo {
    private static SingletonDemo instance;
    private SingletonDemo() {}
    public static SingletonDemo getInstance() {
        if(instance==null) {
            SiSingletonDemo sc;
            synchronized (SingletonDemo.class) {
                sc=instance;
            }
            if(sc==null) {
                synchronized (SingletonDemo.class) {
                    if(sc==null) {
                        sc=new SingletonDemo();
                    }
                }
                instance=sc;
            }
        }
        return instance;
    }
}

4.静态内部类(懒加载)

public class SingletonDemo {
    private static class SingletonClassInstance{
        private static final SingletonDemo instance=new SingletonDemo();
    }
    private SingletonDemo() {}
    public static SingletonDemo getInstance() {
        return SingletonDemo.getInstance();
    }
}

 5.枚举单例模式

public enum SingletonDemo {
    INSTANCE;    //枚举本来就是单例对象
    //避免了反序列和反射的调用
    //缺点,没有延时调用
    public void singletonOperation() {
        
    }
}

 6.统一建模语言UML(unified modeling language)

可以拖动类做uml图

利用反射破解单例设计模式(不包含枚举单例,因为枚举型单例是利用JVM底层实现的单例设计模式)

public class TestSingleObject {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        SingleObject s1=SingleObject.getInstance();
        SingleObject s2=SingleObject.getInstance();
        
        Class<SingleObject> clazz=(Class<SingleObject>) Class.forName("com.littlepage.singletonPattern.SingleObject");
        Constructor<SingleObject> c=clazz.getDeclaredConstructor(null);
        c.setAccessible(true);//跳过检测
        SingleObject s3=c.newInstance();
        SingleObject s4=c.newInstance();
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);
    }
}

解决方法,在空参构造中加入

if(SingletonObject!=null){

throw new runtimeExpection();

}

进行调用时抛出异常就行

//举例
public class SingleObject {
    public static class SingleObjectInstance{
        public static final SingleObject instance=new SingleObject();
    }
    private SingleObject(){
        if(SingleObjectInstance.instance!=null){
            try {
                throw new Exception("运行时异常");
                
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
    }
    public static SingleObject getInstance(){
        return SingleObjectInstance.instance;
    }
}

 利用序列化反序列化进行破解

public class TestSingleObject {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        SingleObject s1=SingleObject.getInstance();
        System.out.println(s1);
        FileOutputStream fops=new FileOutputStream("d:/a.txt");
        ObjectOutputStream oops=new ObjectOutputStream(fops);
        oops.writeObject(s1);
        oops.close();
        
        ObjectInputStream ois =new ObjectInputStream(new FileInputStream("d:/a.txt"));
        SingleObject s2=(SingleObject) ois.readObject();
        System.out.println(s2);
        ois.close();
        
    }
}

解决办法:

private Object resdResolve() throws ObjectStreamException{
        return SingleObjectInstance.instance;
    }

添加该代码,可以使读取Object时直接返回已经存在的实例

原文地址:https://www.cnblogs.com/littlepage/p/9977450.html