设计模式
七大软件设计原则
开闭原则
对扩展开放,对修改关闭
依赖倒置原则
高层次模块不依赖于低层次模块,二者相互依赖其抽象
单一指责原则
一个接口/方法/类只负责一个职责或者一类职责
接口隔离原则
使用多个接口去分别对应不同的方法,而不是使用一个接口囊括全部
迪米特法则
也叫最少知道原则,一个对象应该对其它对象保持最少的了解
里氏替换原则
子类可以扩展父类的功能,但不能替换
合成复用原则
多使用组合/聚合,而不是使用继承
创建型模式
单例模式
-
饿汉式单例
在类初始化的时候创建单例对象
- 优点:效率高、线程安全
- 缺点:单例多的时候会造成内存浪费、反射、序列化可以破坏单例
-
懒汉式单例
对象使用的时候才进行创建,有三种模式
-
synchronized关键字
- 性能不好
-
双重检查锁
- 可以被反射、序列化破坏
- 第一次:减少锁竞争
- 第二次:判断是否需要创建实例
-
匿名内部类
- 可以被反射、序列化破坏
-
-
注册式单例
-
容器式单例
- 反射、序列化破坏
-
枚举式单例
- jdk层面避免了反射以及序列化破坏单例的情况发生
-
工厂模式
-
简单工厂模式
-
一个工厂,专门去创建对象,在工厂中一个方法创建一个对象
- 不符合开闭原则
-
-
工厂方法模式
-
不同产品有各自专业的工厂去创建,一个工厂负责创建一个对象
- 解决简单工厂模式不符合开闭原则的问题
-
-
抽象工厂模式
-
创建一个产品族的工厂
- 相对于工厂方法模式,抽象工厂模式进行了维度的升级,但并不符合开闭原则,所以慎用
-
原型模式
-
浅克隆
-
复制值、引用对象的地址不变,浅克隆对象的引用对象属性与原对象使用同一个
- 工作中使用
-
-
深克隆
-
复制值与引用对象的地址,与原对象是完全两个对象
- 序列化
- 递归赋值
-
建造者模式
- 链式模式,参考StringBuilder()
结构型模式
代理模式
-
静态代理
-
动态代理
-
jdk(Spring默认使用jdk代理)
-
继承InvocationHandler接口,重写invoke()方法
jdk动态代理的步骤:
1、获取被代理对象的引用,并且反射获取它所有的接口
2、jdk动态代理类重新生成一个新的类,同时新的类要实现被代理类实现的所有接口
3、动态生成java代码,根据新加的业务方法生成
4、编译新生成的class文件,重新运行
-
-
cgLIB
-
实现MethodInterceptor 接口,重写 intercept 方法
创建被代理的类及方法;
创建一个实现接口 MethodInterceptor 的代理类,重写 intercept 方法;
创建获取被代理类的方法 getInstance(Object target);
获取代理类,调用代理类方法。
-
-
jdk与cgLIB代理的区别
-
代理条件
- jdk需要被代理类有实现接口
- cgLIB要求被代理类能被继承
-
代理方式
- jdk通过反射调用
- cgLIB通过FastClass直接调用方法(代理和被代理类的方法有index),执行效率效率高
-
代理类生成方式
- 都是在运行时生成字节码,jdk直接写Class字节码
- cgLIB通过ASM框架生成,生成代理类的效率低,但是调用的效率高
-
-
门面模式
- 定义统一的调用接口,方便调用
适配器模式
- 将两个毫无关系的类产生联系
装饰器模式
- 不改变原有类的基础上,将功能扩展
组合模式
- 树型结构
享元模式
- 线程池的思想
行为型模式
责任链模式
- 责任链化,自动传递
策略模式
- 同一行为有不同的实现,并且结果相同,需要知道策略
委派模式
- 不关心实现,委派他人,只要结果