学习设计模式的意义
封装性
、继承性
和多态性
以及类的关联关系和组合关系的充分理解思维能力
,编程能力
和设计能力
标准化
、代码编制更加工程化
、使软件开发效率大大提高,从而缩短软件的开发周期// 饿汉式单例
public class Hungry {// 可能会很浪费空间private byte[] data1 = new byte[1024*1024];private byte[] data2 = new byte[1024*1024];private byte[] data3 = new byte[1024*1024];private byte[] data4 = new byte[1024*1024];private byte[] data5 = new byte[1024*1024];// 私有化构造方法private Hungry(){}private final static Hungry HUNGRY = new Hungry();// 对外提供一个开放的接口,用于返回实例对象public static Hungry getInstance(){return HUNGRY;}}
存在多线程并发模式,后面的DCL懒汉式解决并发问题
public class LazyMan {private LazyMan(){System.out.println(Thread.currentThread().getName()+"ok");}private static LazyMan lazyMan;// 双重检测锁模式的 懒汉式单例 DCL懒汉式public static LazyMan getInstance(){if(lazyMan == null){lazyMan = new LazyMan();// 不是一个原子性操作}return lazyMan;}/** lazyMan = new LazyMan();* 1. 分配内存空间* 2. 执行构造方法,初始化对象* 3. 把这个对象指向这个空间** 123* 132 A* B // 此时lazyMan还没有完成构造* */// 多线程并发public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(()->{LazyMan instance = LazyMan.getInstance();System.out.println(instance.hashCode());}).start();}}
}
注意:synchronized
解决并发问题,但是因为lazyMan = new LazyMan();
不是原子性操作(可以分割,见代码注释),可能发生指令重排序的问题,通过 volatile
来解决
volatile
和 synchronized
两个关键字来保证线程之间操作的有序性,volatile
是因为其本身包含“禁止指令重排序”的语义,synchronized
是由“一个变量在同一个时刻只允许一条线程对其进行lock
操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。public class LazyMan {// 私有化构造器private LazyMan(){System.out.println(Thread.currentThread().getName()+"ok");}private static volatile LazyMan lazyMan;// Double Check Lock 双重检测锁模式的懒汉式单例public static LazyMan getInstance(){if( lazyMan == null ){synchronized (LazyMan.class){ // synchronized加锁解决多线程下的问题if(lazyMan == null){lazyMan = new LazyMan();}}}return lazyMan;}// 多线程并发public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(()->{LazyMan instance = LazyMan.getInstance();System.out.println(instance.hashCode());}).start();}}
}
// 静态内部类
public class Holder {// 构造器私有private Holder(){}public static Holder getInstance(){return InnerClass.HOLDER;}public static class InnerClass{private static final Holder HOLDER = new Holder();}}
public enum EnumSingle {INSTANCE;public EnumSingle getInstance(){return INSTANCE;}
}class Test01{public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {EnumSingle instance = EnumSingle.INSTANCE;Constructor declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class, int.class);declaredConstructor.setAccessible(true);EnumSingle enumSingle = declaredConstructor.newInstance();System.out.println(instance);System.out.println(enumSingle);}
}
注意: 枚举的唯一性,无法通过反射的方式创建枚举对象
Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects at java.lang.reflect.Constructor.newInstance(Constructor.java:417) at com.ppt.design.Test01.main(EnumSingle.java:18)
public class LazyMan {private static boolean flag = false; // 红绿灯解决通过反射创建对象(反编译可以破解该方法)// 私有化构造器private LazyMan(){synchronized (LazyMan.class){if(flag == false){flag = true;}else{throw new RuntimeException("不要试图使用反射破坏单例");}}System.out.println(Thread.currentThread().getName()+"ok");}private static volatile LazyMan lazyMan;// Double Check Lock 双重检测锁模式的懒汉式单例public static LazyMan getInstance(){if (lazyMan == null) {lazyMan = new LazyMan();}return lazyMan;}// 反射public static void main(String[] args) throws Exception {// LazyMan instance = LazyMan.getInstance();Field flag = LazyMan.class.getDeclaredField("flag");flag.setAccessible(true);Constructor declaredConstructor = LazyMan.class.getDeclaredConstructor(null);declaredConstructor.setAccessible(true); // 无视私有的构造器LazyMan lazyMan = declaredConstructor.newInstance();flag.set(lazyMan,false);System.out.println(lazyMan.hashCode());LazyMan lazyMan1 = declaredConstructor.newInstance();System.out.println(lazyMan1.hashCode());}
}