设计模式笔记
设计模式
OOP面向对象编程七大原则
开闭原则:对扩展开发,对修改关闭,尽量不要修改原来的代码
里氏替换原则:继承要保证父类的性质在子类中依然成立
依赖倒置原则:要面向接口编程
单一职责原则:控制类的粒度大小, 将对象解耦
接口隔离原则:为各个类建立需要的专用接口
迪米特原则:只和朋友交流,不与陌生人交谈
合成复用原则:先使用组合或者聚合等关联关系来实现,其次再考虑继承关系
单例模式
饿汉式
// 饿汉式 public class Hungry { private Hungry() { } private static Hungry Hungry = new Hungry(); public static Hungry getInstance() { return Hungry; } }
懒汉式
{ private LazyMan() { System.out.println(Thread.currentThread().getName()); } // 使用volatile防止指令重排 private static volatile LazyMan lazyMan; // 双重检测锁模式dcl懒汉式 public static LazyMan getInstance() { if(lazyMan == null) { synchronized (LazyMan.class) { if(lazyMan == null) { lazyMan = new LazyMan(); } } } return lazyMan; } // 多线程并发 public static void main(String[] args) { for (int i = 0; i <10; i++) { new Thread(()->{ LazyMan.getInstance(); },String.valueOf(i)).start(); } } }
静态内部类
public class Holder { private Holder() { } public static class InnerClass { private static final Holder HOLDER = new Holder(); } public static Holder getInstance() { return InnerClass.HOLDER; } }
单例不安全可以通过反射破坏
// 懒汉式单例 public class LazyMan { private LazyMan() { System.out.println(Thread.currentThread().getName()); } private static LazyMan lazyMan; public static LazyMan getInstance() { if (lazyMan == null) { synchronized (LazyMan.class) { if (lazyMan == null) { lazyMan = new LazyMan(); } } } return lazyMan; } public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { LazyMan instance = LazyMan.getInstance(); LazyMan instance2 = LazyMan.getInstance(); System.out.println(instance == instance2); // 正常,true Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null); // 设置在使用构造器的时候不执行权限检查,破坏程序的封装性和安全性 declaredConstructor.setAccessible(true); LazyMan instance3 = declaredConstructor.newInstance(); LazyMan instance4 = declaredConstructor.newInstance(); //问题1: System.out.println(instance == instance3); // false
// 问题2
System.out.println(instance == instance3); // false
} }
问题1解决,修改构造函数,加同步锁
private LazyMan() { synchronized (LazyMan.class) { if (lazyMan != null) { throw new RuntimeException("error"); } } }
问题2,解决
private static boolean henry = false; private LazyMan() { synchronized (LazyMan.class) { if (!henry) { henry = true; } else { throw new RuntimeException("error"); } } }
枚举
public enum EnumSingle { INSTANCE; public static EnumSingle getInstance() { return INSTANCE; } } class Test { public static void main(String[] args) throws Exception { EnumSingle instance1 = EnumSingle.getInstance(); Constructor<EnumSingle> constructor = EnumSingle.class.getDeclaredConstructor(null); constructor.setAccessible(true); EnumSingle instance2 = constructor.newInstance(); // java.lang.NoSuchMethodException System.out.println(instance1 == instance2); } }
反编译EnumSingle.class,发现也有个无参构造
使用Jad程序EnumSinle.class变为java文件,实际上是有个两个参数的构造
修改代码,才会报错反射不能破坏枚举单例
Constructor<EnumSingle> constructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
工厂模式
简单工厂模式
public interface Car { public void name(); } public class Odi implements Car{ @Override public void name() { System.out.println("奥迪"); } } public class Tesla implements Car{ @Override public void name() { System.out.println("特斯拉"); } }
静态工厂
// 静态工厂模式 // 增加一个新的,必须要修改代码 public class CarFactory { // 方法1 public static Car getCar(String name) { if(name.equals("奥迪")) { return new Odi(); } else if(name.equals("特斯拉")) { return new Tesla(); } else { return null; } } // 方法2 public static Car getOdi() { return new Odi(); } public static Car getTesla() { return new Tesla(); } }
消费者
// 使用具体的实现类买车 Car car = new Odi(); // 使用工厂 Car car1 = CarFactory.getCar("奥迪"); car1.name();
工厂方法模式
// 工厂方法模式 public interface CarFactory { public Car getCar(); } public class OdiFactory implements CarFactory{ @Override public Car getCar() { return new Odi(); } }
public class TeslaFactory implements CarFactory{
@Override
public Car getCar() {
return new Tesla();
}
}
消费者从对应的OdiFactory或者TeslaFactory
Car car = new OdiFactory().getCar(); Car car1 = new TeslaFactory().getCar();
在结构复杂,代码复杂度上简单工厂模式好
根据开闭设计原则,工厂方法模式符合