设计模式指南
大约 4 分钟
10.1 单例模式
单例模式使⽤场景:
- 业务系统全局只需要⼀个对象实例,⽐如加密工具类、JWT工具类、雪花ID工具类、枚举类、状态值等。
- Spring IOC容器中的 Bean 默认就是单例。
- Spring Boot 中的 Controller、Service、Dao 层中通过 @Autowire的依赖注⼊对象默认都是单例的。
单例模式分类:
- 懒汉:就是所谓的懒加载,延迟创建对象,需要用的时候再创建对象。
- 饿汉:与懒汉相反,提前创建对象。
单例模式实现步骤:
- 私有化构造函数。
- 提供获取单例的⽅法。
10.2 代理模式
10.2.1 静态代理
- 一定程度上降低了系统的耦合度,扩展性好。
- 通过代理,将被代理对象 “增强”!(即,扩展被代理对象的功能,可以在代理类处理之前之后增加其他的操作)
- 可以起到保护目标对象的作用
缺点:需要手动创建代理类,如果需要代理的对象多了,那么代理类也越来越多。
10.2.2 动态代理
10.2.2.1 JDK 动态代理
- 实现InvocationHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知。使用Proxy生成实例。
10.2.2.2 CGLIB动态代理
- 实现MethodInterceptor接口,使用intercept()方法进行面向切面的处理,调用相应的通知
性能区别:
1、CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
2、在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理。
应用场景:
- 扩展某个类的某个功能时,spring中的AOP切面增强,比如说:日志
- 当我们想要隐藏某个类时,可以为其提供代理类
- 当一个类需要对不同的调用者提供不同的调用权限时,可以使用代理类来实现(代理类不一定只有一个,我们可以建立多个代理类来实现,也可以在一个代理类中金进行权限判断来进行不同权限的功能调用)
10.3工厂模式
- 工厂模式的目的是为了实现解耦,将对象的创建和使用分开,即应用程序将对象的创建和初始化职责交给工厂对象。
- 降低代码重复。如果对象B的创建过程比较复杂,并且很多地方都用到了,那么很可能出现很多重复的代码,通过统一将创建对象B的代码放到工厂里面统一管理,可以减少代码的重复率,同时也方便维护。相比于构造函数来说,复杂的初始化,会使得构造函数非常的复杂。
- 类本身有很多子类,并且经常性发生变化
应用场景:
- 构造es查询
- lombok中的@build,通过. . 的方式构造类
- Spring框架的IOC就是基于工厂模式,IOC通过DI(依赖注入)的方式将bean的创建交给了Spring Container,Spring Container 自动帮我们创建对象,我们只需要使用即可
10.4策略模式
策略模式的主要目的是将行为与具体的算法或者实现进行分开。一个类的行为或算法可以在运行时更改。
减少if-else代码,减少耦合度,方便维护,不同的实现做单一的功能。
- 算法可以自由切换。
- 避免使用多重条件判断
- 扩展性良好
应用场景:
- 文件解析,不同的Excel处理方式不同,入库也不同
- 数据隔离,不同权限的用户看到的数据是不一样的
- 下单的时候,根据用户选择的不同的付款方式(主要的付款方式有一次性付款,分期付款,按揭付款,首付分期按揭付款),生成对应的 应收明细集合
- app分享功能,可以分享到 【朋友圈,微信好友,sina,qq】四个地方,分别调用不同的分享入口
