package com.learn.design.pattern.creational.singleton;import java.io.Serializable;public class HungrySingleton implements Serializable,Cloneable{private final static HungrySingleton hungrySingleton;static{hungrySingleton = new HungrySingleton();}/*** 我们关注的是私有构造器* 那因为这个构造器是私有的* 在Test里面是无法new的* 但是我们能不能通过反射* 并且把构造器的权限打开* 然后去获取这个对象* 我们现在来试一下* 先不打开他的权限* * */private HungrySingleton(){/*** 直接在这里面做一个判断* 如果这个不是空* 那我们就直接throw一个异常* 异常是一个runtimeException* 里面写上"单例构造器禁止反射调用"* 那我们现在再回到Test里面* 可以看到我们的异常已经打印出来* 单例构造器禁止反射调用* 那这种方式有一种特点* 也就是在类加载这个时刻就把类加载好了* 这种类是OK的* 对于这种单例模式有效的* 那还有那种单例模式可以用呢* 很简单那就是静态类* * */if(hungrySingleton != null){throw new RuntimeException("单例构造器禁止反射调用");}}public static HungrySingleton getInstance(){return hungrySingleton;}/*** 现在序列化和反序列化方法已经有了* * * @return*/private Object readResolve(){return hungrySingleton;}@Overrideprotected Object clone() throws CloneNotSupportedException {return getInstance();}
}
package com.learn.design.pattern.creational.singleton;import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//        LazySingleton lazySingleton = LazySingleton.getInstance();//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());//        Thread t1 = new Thread(new T());
//        Thread t2 = new Thread(new T());
//        t1.start();
//        t2.start();
//        System.out.println("program end");//        HungrySingleton instance = HungrySingleton.getInstance();
//        EnumInstance instance = EnumInstance.getInstance();
//        instance.setData(new Object());
//
//        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
//        oos.writeObject(instance);
//
//        File file = new File("singleton_file");
//        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
//
//        HungrySingleton newInstance = (HungrySingleton) ois.readObject();
//        EnumInstance newInstance = (EnumInstance) ois.readObject();
//
//        System.out.println(instance.getData());
//        System.out.println(newInstance.getData());
//        System.out.println(instance.getData() == newInstance.getData());Class objectClass = HungrySingleton.class;
//        Class objectClass = StaticInnerClassSingleton.class;//        Class objectClass = LazySingleton.class;
//        Class objectClass = EnumInstance.class;/*** 用构造器这个类* 反射里边的* 声明的构造器getDeclaredConstructor* 报红线了* 有异常* 直接抛出* 那我们在写实际业务的时候* 根据业务场景确定向上抛出还是try catch* 那我们这里面为了方便* 所以都在主函数里边抛出了* 这个也是一样的* * * */Constructor constructor = objectClass.getDeclaredConstructor();
//        Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
///*** 我们设置一下权限* */constructor.setAccessible(true);
//        EnumInstance instance = (EnumInstance) constructor.newInstance("Geely",666);//
//        LazySingleton newInstance = (LazySingleton) constructor.newInstance();
//        LazySingleton instance = LazySingleton.getInstance();//        StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
//        StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();/*** 我们再拿一个对象* 爆红了看一下* 抛出异常* 然后呢强转* * */HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();/*** 首先我们从这个类里面拿到一个instance* 直接调用它的getInstance* * */HungrySingleton instance = HungrySingleton.getInstance();/*** 我们把这两个也看一下* 结果已经出来了* 我们看一下* 通过反射把这个权限置为true的话* 那他的构造器private* 这个权限就放开了* 所以Test里面调用newInstance的时候* 就直接调用了这个构造器* 对象就实例化出来了* 我们看一下这两个不是同一个对象* 结果也是false* 那对于饿汉式有什么特点呢* 首先它是在类加载的时候就生成了这个实例* 那是因为它是在类加载的时候生成* 所以我们可以在构造器里面进行一个判断* 现在我们就写一下反射防御的一些代码* * * */System.out.println(instance);System.out.println(newInstance);System.out.println(instance == newInstance);//        EnumInstance instance = EnumInstance.getInstance();
//        instance.printTest();}
}
package com.learn.design.pattern.creational.singleton;public class StaticInnerClassSingleton {private static class InnerClass{private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();}public static StaticInnerClassSingleton getInstance(){return InnerClass.staticInnerClassSingleton;}/*** 我们现在把防止单列反射的代码也加上* StaticInnerClassSingleton这个是私有构造器* InnerClass.staticInnerClassSingleton* 这样这段防御代码也加好了* 我们再run一下Test* 异常就正如我们期望的抛出了* 那这两个单例模式* 刚刚说了* 他们的特点就是在他们加载的时候* 这个实例就会生成好* 因为这是静态内部类* 前面我们已经讲了* InnerClass.staticInnerClassSingleton;* 里面调用静态内部类* 然后就会把这个对象new出来* staticInnerClassSingleton = new StaticInnerClassSingleton();* 这里就不debug了* debug也会到这里面抛出异常* 很简单* 那接下来要说的是* 对于不是在类加载的时候* 创建单例对象的* 这种情况* 我们也来测试一下* 我们来看一下* 有懒汉式的* 我们随便选一个* 选一个简单的就可以* 这两个并没有什么区别* 因为他们都不是在类加载的时候就初始化对象了* 我们就用LazySingleton* * */private StaticInnerClassSingleton(){if(InnerClass.staticInnerClassSingleton != null){throw new RuntimeException("单例构造器禁止反射调用");}}
}
package com.learn.design.pattern.creational.singleton;import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//        LazySingleton lazySingleton = LazySingleton.getInstance();//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());//        Thread t1 = new Thread(new T());
//        Thread t2 = new Thread(new T());
//        t1.start();
//        t2.start();
//        System.out.println("program end");//        HungrySingleton instance = HungrySingleton.getInstance();
//        EnumInstance instance = EnumInstance.getInstance();
//        instance.setData(new Object());
//
//        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
//        oos.writeObject(instance);
//
//        File file = new File("singleton_file");
//        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
//
//        HungrySingleton newInstance = (HungrySingleton) ois.readObject();
//        EnumInstance newInstance = (EnumInstance) ois.readObject();
//
//        System.out.println(instance.getData());
//        System.out.println(newInstance.getData());
//        System.out.println(instance.getData() == newInstance.getData());//        Class objectClass = HungrySingleton.class;Class objectClass = StaticInnerClassSingleton.class;//        Class objectClass = LazySingleton.class;
//        Class objectClass = EnumInstance.class;Constructor constructor = objectClass.getDeclaredConstructor();
//        Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
//constructor.setAccessible(true);
//        EnumInstance instance = (EnumInstance) constructor.newInstance("Geely",666);//
//        LazySingleton newInstance = (LazySingleton) constructor.newInstance();
//        LazySingleton instance = LazySingleton.getInstance();/*** 这两个是不同的对象* * */StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();//        HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();
//        HungrySingleton instance = HungrySingleton.getInstance();System.out.println(instance);System.out.println(newInstance);System.out.println(instance == newInstance);//        EnumInstance instance = EnumInstance.getInstance();
//        instance.printTest();}
}

package com.learn.design.pattern.creational.singleton;/*** * @author Leon.Sun**/
public class LazySingleton {/*** 首先他在类加载的时候没有生成* 只有调用getInstance方法的时候* 才会生成这个对象* * */private static LazySingleton lazySingleton = null;/*** */private LazySingleton(){/*** 如果把这段代码加载这里边* 这个就和我们创建实例的顺序有关了* 为什么这么说呢* 回到Test里边* 我们是先调用的getInstance* 而且这个方法是同步方法* * */if(lazySingleton != null){throw new RuntimeException("单例构造器禁止反射调用");}}public synchronized static LazySingleton getInstance(){
//    public static LazySingleton getInstance(){
//      synchronized (LazySingleton.class) {if(lazySingleton == null){/*** 先调用之后这个对象就会new出来* 后调用的反射的时候* 也就走到异常里面了* 那run一下看一下现在的效果* 效果和哦我们预期的是一致的* */lazySingleton = new LazySingleton();}
//      }return lazySingleton;}//    public static void main(String[] args) throws Exception {
//        Class objectClass = LazySingleton.class;
//        Constructor c = objectClass.getDeclaredConstructor();
//        c.setAccessible(true);
//
//        LazySingleton o1 = LazySingleton.getInstance();
//        System.out.println("Program end.....");
//
//        Field flag = o1.getClass().getDeclaredField("flag");
//        flag.setAccessible(true);
//        flag.set(o1,true);
//
//
//        LazySingleton o2 = (LazySingleton) c.newInstance();
//
//        System.out.println(o1);
//        System.out.println(o2);
//        System.out.println(o1==o2);
//    }}
package com.learn.design.pattern.creational.singleton;import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//        LazySingleton lazySingleton = LazySingleton.getInstance();//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());//        Thread t1 = new Thread(new T());
//        Thread t2 = new Thread(new T());
//        t1.start();
//        t2.start();
//        System.out.println("program end");//        HungrySingleton instance = HungrySingleton.getInstance();
//        EnumInstance instance = EnumInstance.getInstance();
//        instance.setData(new Object());
//
//        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
//        oos.writeObject(instance);
//
//        File file = new File("singleton_file");
//        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
//
//        HungrySingleton newInstance = (HungrySingleton) ois.readObject();
//        EnumInstance newInstance = (EnumInstance) ois.readObject();
//
//        System.out.println(instance.getData());
//        System.out.println(newInstance.getData());
//        System.out.println(instance.getData() == newInstance.getData());//        Class objectClass = HungrySingleton.class;
//        Class objectClass = StaticInnerClassSingleton.class;Class objectClass = LazySingleton.class;
//        Class objectClass = EnumInstance.class;Constructor constructor = objectClass.getDeclaredConstructor();
//        Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
//constructor.setAccessible(true);
//        EnumInstance instance = (EnumInstance) constructor.newInstance("Geely",666);//LazySingleton newInstance = (LazySingleton) constructor.newInstance();/*** 直接用LazySingleton去getInstance* 因为执行到这里的时候单例已经存在了* 所以这里抛出异常* 但是如果我们把这个顺序调换一下* 我们再run一下* 可以看到结果* 完全不一样* 两个不同的对象都出来了* 并且是false* 但是如果多线程的情况下* 例如反射一个线程* 获取单例一个线程* 那这个就不一定了* 看CPU的分配* 如果是反射的线程* 先实例化对象的话* 那这个单例对象可就不止一个对象了* 那有的人会说* 那像刚才饿汉式* 内部类调换顺序* 会不会也这样呢* 但是不会的* 因为这两个是在类加载的时候就把对象初始化好了* 那我们也简单测试一下* * */LazySingleton instance = LazySingleton.getInstance();//        StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
//        StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();//        HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();
//        HungrySingleton instance = HungrySingleton.getInstance();System.out.println(instance);System.out.println(newInstance);/*** 结果也能够猜到不是同一个对象* * */System.out.println(instance == newInstance);//        EnumInstance instance = EnumInstance.getInstance();
//        instance.printTest();}
}
package com.learn.design.pattern.creational.singleton;import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//        LazySingleton lazySingleton = LazySingleton.getInstance();//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());//        Thread t1 = new Thread(new T());
//        Thread t2 = new Thread(new T());
//        t1.start();
//        t2.start();
//        System.out.println("program end");//        HungrySingleton instance = HungrySingleton.getInstance();
//        EnumInstance instance = EnumInstance.getInstance();
//        instance.setData(new Object());
//
//        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
//        oos.writeObject(instance);
//
//        File file = new File("singleton_file");
//        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
//
//        HungrySingleton newInstance = (HungrySingleton) ois.readObject();
//        EnumInstance newInstance = (EnumInstance) ois.readObject();
//
//        System.out.println(instance.getData());
//        System.out.println(newInstance.getData());
//        System.out.println(instance.getData() == newInstance.getData());Class objectClass = HungrySingleton.class;
//        Class objectClass = StaticInnerClassSingleton.class;//        Class objectClass = LazySingleton.class;
//        Class objectClass = EnumInstance.class;Constructor constructor = objectClass.getDeclaredConstructor();
//        Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
//constructor.setAccessible(true);
//        EnumInstance instance = (EnumInstance) constructor.newInstance("Geely",666);//
//        LazySingleton newInstance = (LazySingleton) constructor.newInstance();
//        LazySingleton instance = LazySingleton.getInstance();//        StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
//        StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();/*** 先反射再获取实例* 结果是一样的* 他的原因前面也强调了* 因为在类加载的时候就把类初始化好了* 接着回到懒汉式来说* * */HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();HungrySingleton instance = HungrySingleton.getInstance();System.out.println(instance);System.out.println(newInstance);System.out.println(instance == newInstance);//        EnumInstance instance = EnumInstance.getInstance();
//        instance.printTest();}
}
package com.learn.design.pattern.creational.singleton;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;/*** 我们在这里面取巧* 比如说* 我们声明一个flag等于0* 调用构造器就赋值flag等于1* 是一个非常复杂的逻辑* 例如flag的各种变化* 甚至取反* 加上各种逻辑判断* 无论增加多么复杂的逻辑* 看上去是可以的* 但是不要忘了我们反射的威力* 反射既然可以拿构造器的权限* 他很自然也可以修改flag* 所以这里创建计数或者信号量* 没有什么意义* 那结论就是对于这种Lazy的情况* 反射就是无法避免的* 这个我们删除* 因为一旦多线程就和顺序有关* 反射先进来那就拿两个对象* 希望能理解这一块* 因为一旦多线程就和顺序有关* 反射如果先进来* 那就拿两个对象了* 那这里我们就较个真* 这里是后来补的* 因为我觉得有必要写一遍反射* 首先我们写一个flag* 直接用布尔类型* 比较简单* * * * @author Leon.Sun**/
public class LazySingleton {private static LazySingleton lazySingleton = null;/*** 默认值就是true* 如果为true这个类还可以进行实例* 否则就抛出异常* 那很简单* 我们在构造器里面进行一个判断* * 现在这个字段并没有get/set方法* 也就是get/set方法在这里并没有什么意义* 反射还是能修改它* 所以就不写了* * * */private static boolean flag = true;private LazySingleton(){/*** 首先这个flag是为true的* * 第二次通过反射* 这个时候flag是false* 所以if进不来* 直接进入到抛出异常里* F8通过* 没有任何问题* 阻止了反射攻击* * 又会来到LazySingleton的构造器* 咱们来看一下* flag为true* flag这个值在内存中已经为true了* 所以这个构造器又调用成功* F8通过* 结果我就打出来了* 声明了两个对象* 并且他们不是同一个对象* 那有的人会说* 我改成final呢* final肯定不行啊* 如果是final的话* flag = false;* 这里是不能够重新赋值的* 也就是说这个开关失效了* 所以说这里逻辑无论多复杂* 反射的时候* 直接修改这个值还是抵挡不住的* 所以有人认为单例模式是最简单的模式* 那看上去的确是最简单的* 但是如果说复杂呢* 他也是最复杂的* 这一块的知识点还是比较值得研究的* 那接下来我们还有一种单例的模式* 这种单例模式呢* 既能防御反射* 又能保证不被序列化破坏* 那他的原理是什么呢* * * */if(flag) {/*** 我们赋值成false* 那如果flag为true的话* 就把它赋值成false* * if进来了把它赋值为false* 注意这里的变化* * 第一次为true* 把它置为false* 没有任何问题* 直接通过F8通过* * */flag = false;}else {/*** else里面就不用判断了* 就是这样的* 所以当第一次调用构造器的时候* 走到if里面是OK的* 第二次他被置成false* 我们期望是走到else里边* * * */throw new RuntimeException("单例构造器禁止反射调用");}
//        if(lazySingleton != null){
//            throw new RuntimeException("单例构造器禁止反射调用");
//        }}public synchronized static LazySingleton getInstance(){
//    public static LazySingleton getInstance(){
//      synchronized (LazySingleton.class) {if(lazySingleton == null){lazySingleton = new LazySingleton();}
//      }return lazySingleton;}/*** 那我们就在这类里边写一个主函数* 测试反射攻击* 前面刚刚说用int* 我们这里采用简单的布尔* 那我们所要说的关键点* 不在于flag是什么类型* 而是在于反射能不能搞定* * * @param args* @throws Exception*/public static void main(String[] args) throws Exception {Class objectClass = LazySingleton.class;/*** 获取他的构造器* 第一个反射包下的* 调用getDeclaredConstructor这个方法* 然后把异常抛出* * */Constructor c = objectClass.getDeclaredConstructor();/*** 设置他的权限为true* 也就是这一条修改了构造器的权限* * */c.setAccessible(true);/*** 现在获取这个对象* 正常的获取这个对象LazySingleton.getInstance()* * */LazySingleton o1 = LazySingleton.getInstance();System.out.println("Program end.....");/*** 现在我们要破坏他* 我们在反射生成o2之前* 把这个字段改掉* 怎么改呢* 非常简单* Field也是反射包下的* 我们从o1里面获得class* 然后获取声明的字段* 这个字段就是flag* 这里面应该有异常* 我们抛出一下* 那这个字段我们就获取到了* 因为这个字段是private的* * 现在到这里边* 我们看一下flag这个对象* 我们可以看到他是private的static的boolean类型的* * */Field flag = o1.getClass().getDeclaredField("flag");/*** 我们把它权限打开* * 现在设置他的权限为true* * */flag.setAccessible(true);/*** set方法就是要把某个对象的值设置成什么* 是哪个对象呢* o1这个对象* value是什么呢* 因为字段本身已经是flag了* 把它呢置成true* 那我们看一下* LazySingleton o2 = (LazySingleton) c.newInstance();* 这个能不能成功呢* 我们先run一下* 看一下结果* 结果已经出来了* 可以看到反射攻击成功* 也就是说我们通过这个反射* 已经把private的flag* 已经置成true了* 所以刚刚我也说* 无论这里边加多复杂的逻辑* 无论是布尔还是int* 都是没有用的* 因为我们通过反射可以任意修改* 接着往下看* 所以我们在这里debug一下* 一起来学习一下反射* 断点过来了* 第一次为true* 把它置为false* * 这个时候把他的值修改掉* o1是什么呢* o1就是这个对象* 也就是上面的getInstance对象* 这个对象是静态的* 所以我修改这个对象的静态属性* 就直接修改掉了* 我们F6单步* 那现在我们再F8一下* * */flag.set(o1,true);/*** 然后我们获取一个o2* 通过反射* c.newInstance()* 然后进行强转* 先抛出异常然后强转* * */LazySingleton o2 = (LazySingleton) c.newInstance();/*** 输出o1和o2* */System.out.println(o1);System.out.println(o2);/*** 然后输出他们想不相等* 结果出来了* 和我们预期的是一样的* 单例构造器禁止调用* 也就是我们加的flag已经生效了* 没有问题* 现在是好使的* 那我们打一个断点来看一下* 我们再debug看一下* * */System.out.println(o1==o2);}
}

单例设计模式-反射攻击解决方案及原理分析相关推荐

  1. 单例设计模式 序列化破坏单例模式原理解析及解决方案?

    单例设计模式 序列化破坏单例模式原理解析及解决方案? 序列化和反序列化 反射的破坏

  2. 结合Spring源码学习单例设计模式

    之前我学习了 Spring Ioc,明白了 Spring IoC 容器是一个管理Bean的容器,在Spring的定义中,它要求所有的IoC容器都需要实现接口 BeanFactory ,它是一个顶级容器 ...

  3. 彻底理解单例设计模式

    单例设计模式 1. 单例模式概念 单例模式(Singleton Pattern)是Java中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个 ...

  4. 单例设计模式(Singleton)附带案例代码仓库

    目录 1 .单例模式的结构 2 .单例模式的实现 2.1.饿汉式(静态变量方式) 2.2.饿汉式(静态代码块方式) 2.3.懒汉式(线程不安全) 2.4.懒汉式(线程安全) 2.5.懒汉式(双重检查锁 ...

  5. Java设计模式—单例设计模式(Singleton Pattern)完全解析

    转载请注明出处:http://blog.csdn.net/dmk877/article/details/50311791 相信大家都知道设计模式,听的最多的也应该是单例设计模式,这种模式也是在开发中用 ...

  6. Java查漏补缺(08)关键字:static、单例设计模式、理解main方法、类的成员之四:代码块、final关键字、抽象类、接口、内部类、枚举类、注解、包装类

    Java查漏补缺(08)关键字:static.单例设计模式.理解main方法.类的成员之四:代码块.final关键字.抽象类.接口.内部类.枚举类.注解.包装类 本章专题与脉络 1. 关键字:stat ...

  7. java单例设计模式

    单例模式的概念 单例类只有一个实例,并且只由自己创建,实例化后向整个系统提供自己的实例. 单例设计模式主要分为2种:懒汉式和饿汉式.2者的区别在于初始化的时间不同. 像线程池,缓存,日志等都被设计成单 ...

  8. 菜鸟之路-浅谈设计模式之单例设计模式

    单例设计模式 定义:确保一个类仅仅有一个实例,并且自行实例化并向整个系统提供这个实例. 单例模式是一种经常使用的软件设计模式.在它的核心结构中仅仅包括一个被称为单例的特殊类. 通过单例模式能够保证系统 ...

  9. GOF设计模式之1:单例设计模式

    1.单例设计模式核心作用: 保证一个类只有一个实例,并且提供了访问该实例的全局访问点 2.常见应用场景: window的任务管理器 项目中读取配置文件一般也是一个单例模式 数据库连接池的设计也是采用单 ...

最新文章

  1. 写一个比较全的进制转换函数--ic
  2. mysql 6.3 入门_Mysql 入门小练习
  3. iBATIS In Action:使用映射语句(二)
  4. 关于移动端的一些tip
  5. HOW-TO:带有Spring MVC的Tomcat中的自定义错误页面
  6. IO流练习题 实现图片的加密解密操作
  7. linux中pri=100,浅析Linux中PRI和NI的关系
  8. seo按天扣费系统_网站seo优化多少钱,SEO快速排名按天扣费怎么样
  9. 操作系统–银行家算法c语言代码
  10. 蓝桥杯C语言基础训练答案,蓝桥杯c语言答案.doc
  11. 百度离线语音合成SDK使用
  12. npm install 报警告npm WARN
  13. wp8.1 java_巨硬的内部比较——WP8.1版本与WP10系统对比(以lumia640为例)
  14. 无线路由器DNS服务器异常,fast无线路由器dns异常的解决方法
  15. git操作与vscode,码市的结合
  16. django自动生成问卷表的软件的设计与实现毕业设计源码291138
  17. 6个在线正则表达式工具
  18. C51中的INTRINS.H:内部函数
  19. 我在赶集网的两个月(完整版)
  20. 照片、摄影处理中的基本知识

热门文章

  1. 打开AzureRay园子的大门,欢迎大家串门哟~
  2. HDU 4869 Turn the pokers(思维+组合公式+快速幂)
  3. 程序员编程艺术第一~十章集锦与总结(教你如何编程)--持续更新中
  4. ProxySQL MySQL MGR8配置
  5. commons-lang3:ArrayUtils
  6. grenndao 插入表数据报错
  7. Asp.Net MVC 使用FileResult导出Excel数据文件
  8. svn钩子程序上传文件中文文件导致报错的处理办法
  9. 总结一些linux目录结构和终端命令
  10. FastReport人民币大写转换