# design-patterns **Repository Path**: fxbin/design-patterns ## Basic Information - **Project Name**: design-patterns - **Description**: Design Patterns Guide - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-22 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # design patterns ## TODO ### 创建型模式 - [ ] 简单工厂模式 - [ ] 工厂方法模式 - [ ] 抽象工厂模式 - [ ] 建造者模式 - [ ] 原型模式 - [ ] 单例模式 ### 行为型模式 - [X] 责任链模式 —— 以讹传讹 - [ ] 命令模式 - [ ] 解释器模式 - [ ] 迭代器模式 - [ ] 中介者模式 - [ ] 备忘录模式 - [ ] 观察者模式 - [ ] 状态模式 - [X] 策略模式 —— 随机应变 - [X] 模板方法模式 - [ ] 访问者模式 - [X] 代理模式 —— 托孤寄命 ### 结构型模式 - [ ] 适配器模式 - [ ] 桥接模式 - [ ] 组合模式 - [ ] 装饰模式 - [ ] 外观模式 - [ ] 享元模式 - [ ] 代理模式 ### J2EE 模式 - [ ] MVC 模式 - [ ] 业务代表模式 - [ ] 传输对象模式 - [ ] 数据访问对象模式 - [ ] 前端控制器模式 - [ ] 拦截过滤器模式 - [ ] 服务定位器模式 ## 设计模式分类 设计模式总共有 23 种,总体来说可以分为三大类:创建型模式( Creational Patterns )、结构型模式( Structural Patterns )和行为型模式( Behavioral Patterns )。 | 分类 | 关注点 | 包含 | | -- | -- | -- | | 创建型模式 | 关注于对象的创建,同时隐藏创建逻辑 | 工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式 | | 结构型模式 | 关注类和对象之间的组合 | 适配器模式、过滤器模式、装饰模式、享元模式、代理模式、外观模式、组合模式、桥接模式 | | 行为型模式 | 关注对象之间的通信 | 责任链模式、命令模式、中介者模式、观察者模式、状态模式、策略模式、模板模式、空对象模式、备忘录模式、迭代器模式、解释器模式、访问者模式 | ## 责任链设计模式 ### 是什么 * 客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象。 * 多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。 * 将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。其过程实际上是一个递归调用。 > 总结: * 有多个对象共同对一个任务进行处理。 * 这些对象使用链式存储结构,形成一个链,每个对象知道自己的下一个对象。 * 一个对象对任务进行处理,可以添加一些操作后将对象传递个下一个任务。也可以在此对象上结束任务的处理,并结束任务。 * 客户端负责组装链式结构,但是客户端不需要关心最终是谁来处理了任务。 ### 应用场景 * 多条件流程判断:权限控制 * ERP 系统流程审批:总经理、人事经理、项目经理 * Java 过滤器的底层实现 Filter > 总结: > 1、如果一个逻辑是按照一定的步骤进行的,而步骤之间存在复杂的逻辑计算,那么可以考虑使用责任链设计模式; > 2、或者一坨if分支时,也可以考虑使用责任链设计模式 ### 责任链模式的优缺点 #### 优点 * 动态组合,使请求者和接受者解耦。 * 请求者和接受者松散耦合:请求者不需要知道接受者,也不需要知道如何处理。每个职责对象只负责自己的职责范围,其他的交给后继者。各个组件间完全解耦。 * 动态组合职责:职责链模式会把功能分散到单独的职责对象中,然后在使用时动态的组合形成链,从而可以灵活的分配职责对象,也可以灵活的添加改变对象职责。 #### 缺点 * 产生很多细粒度的对象:因为功能处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完,需要很多的职责对象,会产生大量的细粒度职责对象。 * 不一定能处理:每个职责对象都只负责自己的部分,这样就可以出现某个请求,即使把整个链走完,都没有职责对象处理它。这就需要提供默认处理,并且注意构造链的有效性。 ### 责任链总结 * 首先定义一个抽象类,该抽象类定义了请求处理方法和持有对自己的引用(接收下一个处理者) * 继承上面的抽象类,定义具体的请求处理者 * 设置处理请求链,处理请求链,可以在代码中写死,也可以通过存储在数据库中再读取出来。 ## 策略模式 ### 定义 > 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以解决多重 if 判断问题。 ### 结构 * 环境(Context)角色:持有一个 Strategy 的引用。 * 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色 给出所有的具体策略类所需的接口。 * 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。 ### 架构图 ![img 策略模式架构图](images/策略模式架构图.jpg) ### 策略模式优缺点 #### 优点 * 算法可以自由切换(高层屏蔽算法,角色自由切换) * 避免使用多重条件判断(如果算法过多就会出现很多种相同的判断,很难维护) * 扩展性好(可自由添加取消算法而不影响整个功能) #### 缺点 * 策略类数量增多(每一个策略类复用性很小,如果需要增加算法,就只能新增类) * 所有的策略类都需要对外暴露(使用的人必须了解使用策略,这个就需要其它模式来补充,比如工厂模式、代理模式) ### 策略模式应用场景 > 策略模式的应用场景很多,比如商场的促销活动、联合登录(qq、微信)、聚合支付(微信支付、支付宝支付)等。 ## 模板模式 ### 定义 > 将一个操作按照步骤定义在一个方法中,将部分步骤的实现放在子类中完成 ### 为啥使用 * 解决代码复用问题 * 将复杂行为定义为模板 ### 模板方法模式应用场景 > 有多个类,存在共同行为和不同行为,可以考虑使用模板方法设计模式。 > ### 模板方法模式如何定义 `抽象类`:定义并实现一个模板方法。这个模板方法定义了算法的骨架,将共同操作定义在父类中,不同行为抽象到子类实现。 * 模板方法:定义在抽象类中,将多个基本的操作方法组合在一起,形成一个总的行为或者算法。 * 抽象方法: 模板方法中的一个简单操作方法,是特有的,不同行为。 * 具体方法:模板方法中的几个操作方法,是共有的。 `实现类`:实现父类所定义的抽象方法。 ### 模板方法模式优缺点 #### 优点 * 对算法进行封装,保留可变部分供子类扩展。 * 提取公共代码,提高了代码的复用性,维护也更方便。 * 行为由抽象类控制,由子类实现。 #### 缺点 * 每个不同的需求都必须由一个子类来实现 * 子类个数增加,系统会很庞大 ### 模板模式通用实现类图 ![img 模板模式通用实现类图](images/模板模式通用实现类图.jpg) ## 委派模式||代理模式 ### 定义 > 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。说的简单直白一点,其实就是我们生活中的中介。 ### 为什么使用代理模式 中介隔离:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。 ### 静态代理 > 目标对象和代理对象都需要实现相同的接口 ### 动态代理 动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。动态代理也分为 JDK 动态代理和 CGLIB 动态代理。 #### JDK动态代理 * 生成的 $Proxy 代理类继承了 Proxy 类,实现了代理接口 * 生成的代理类,实行目标方法相当于调用的是 InvocationHandler 接口的 invoke 方法 * 由于 Java 不能多继承,这里已经继承了 Proxy 类了,不能再继承其他的类,所以 JDK 的动态代理不支持对实现类的代理,只支持接口的代理。 #### CGLIB 动态代理 ##### 什么是 CGLIB 动态代理 > CGLIB 是一个强大的,高性能,高质量的代码生成类库。它可以在运行期扩展 Java 类与实现 Java 接口。其底层实现是通过 ASM 字节码处理框架来转换字节码并生成新的类。大部分功能实际上是 ASM 所提供的,CGLIB 只是封装了 ASM,简化了 ASM 操作,实现了运行期生成新的 class。 ##### CGLIB 动态代理原理 > 运行时动态的生成一个被代理类的子类(通过 ASM 字节码处理框架实现),子类重写了被代理类中所有非 final 的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势植入横切逻辑。 ### 静态代理与动态代理区别 静态代理需要自己写代理类,而动态代理不需要写代理类。 ### JDK 动态代理与 CGLIB 实现区别 * JDK 动态代理底层实现 JDK 的动态代理使用 Java 的反射技术生成动态代理类,只能代理实现了接口的类, 没有实现接口的类不能实现动态代理。 * CGLIB 动态代理底层实现 运行时动态的生成一个被代理类的子类(通过 ASM 字节码处理框架实现),子类重写了被代理类中所有非 final 的方法,在子类中采用方法拦截的技术拦截所有父类方法的调用,不需要被代理类对象实现接口,从而 CGLIB 动态代理效率比 Jdk 动态代理反射技术效率要高。