行为型
- 共11种
- 策略、模版方法、观察者、访问者、中介者、迭代器、职责链、备忘录、命令、状态、解释器
策略模式
-
概念
它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户
-
优点
- 完美符合开闭原则,可以在不修改原系统的基础上选择算法和行为,也可以灵活的新增
- 可以避免使用多重条件转移语句,即if else
-
缺点
- 客户端必须知道所有的策略,并自行决定使用哪一种策略
- 策略模式将造成很多策略类和对象,可以通过使用享元模式在一定程度上减少对象的数量
-
使用场景★★★★☆
- 如果一个系统中有许多类,他们的区别仅限于他们的行为,可以使用策略模式动态地让一个对象在许多行为中选择一种行为
- 系统需要在几种算法中选择一种
- 规避多重的条件选择语句的场景
-
个人理解:策略模式即使与简单工厂模式组合,还是需要必要的if或switch判断。可以把这些判断条件加入到各个算法中,让算法自己匹配
状态模式
-
概念
当一个对象的内在状态改变时,允许改变其行为,这个对象看起来就像是改变了其类
-
优点
- 封装了转换规则,不需要通过条件判断语句来进行状态的判断和转移,提高了代码的可维护性
- 将所有与某个状态有关的行为封装到一个类中,可以方便的增加新的状态
-
缺点
- 状态模式的使用必然会增加系统类和对象的个数
- 结果和实现都比较困难,实现不当会导致代码混乱
-
使用场景★★★☆☆
- 对象的行为依赖于它的状态,并且可以根据它的状态改变,改变它的行为。例如银行账号,不同状态时,行为有差异
-
代码中包含大量与对象状态有关的条件语句时
观察者模式
-
概念
定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们能够自动更新自己
-
优点
- 可以实现表现层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口
- 观察者模式在观察目标和观察者之间建立了一个抽象耦合,使他们属于不同的抽象化层次
- 简化了一对多的设计难度,符合开闭原则
-
缺点
- 如果观察者和被观察者有循环依赖,可能会触发循环调用,导致系统崩溃
-
使用场景★★★★★
- 一个抽象模型有两个方面,其中一个方面依赖另一个方面。将这些对象封装在独立的对象中使它们可以各自独立地改变和复用
-
需要在用户中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象,可以使用观察者模式创建一种链式触发机制
职责链模式
-
概念
使多个对象都有机会处理请求,从而避免请求的发送者与请求的接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。
-
优点
- 降低耦合度:接收者和发送者都没有对方的明确信息,且链中对象不需要知道链的结构,由客户端负责链的创建
- 简化对象之间的相互连接,增强给对象指派职责的灵活性
- 增加新的请求处理类很方便:在系统中增加一个新的具体请求处理者无需修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看符合开闭原则。
-
缺点
- 不能保证请求一定会被接收。既然请求没有了明确的接收者,那么就不能保证它一定会被处理
- 对于较长的职责链,请求的处理可能涉及到多个处理对象,系统性能受到一定影响,而且代码调试不方便
-
使用场景★★☆☆☆
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定
- 可动态指定一组对象处理请求
-
个人理解:可以和观察者模式结合,每个对象处理完,指定下一个处理的对象,然后放到EventBus中,post后,下一个对象自动处理请求
模版方法模式
-
概念
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤
-
优点
- 把不变的行为搬移到超类,去除子类中的重复代码
- 模板方法是一种代码复用的基本技术,它在类库设计中非常重要,提取了类库中的公共行为,将公共行为放到父类中,而通过其子类来实现不同的行为
- 是一种反向的控制结构,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合开闭
-
缺点
- 每个而不同的实现都需要定义一个子类,这回导致类的个数增加,系统更加庞大,设计也更加抽象,但是更加符合”单一职责原则“,使得类的内聚性更高
-
使用场景★★★☆☆
- 一次性实现一个算法的不变部分,将可变性为留给子类来实现
- 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类实现
-
广泛应用于框架设计(Spring、Struts等)中,以确保父类控制处理流程的逻辑顺序(如框架的初始化)
迭代器模式
-
概念
提供一个方法,顺序访问一个聚合对象中的各个元素,而又不暴露对象的内部表示
-
优点
- 简化了聚合类
- 新增聚合类和迭代器类都很方便,无需修改原有代码,满足”开闭原则“的要求
-
缺点
- 由于迭代器模式将存储数据和遍历数据的职责分开,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性
-
使用场景★★★★★
- 为遍历不同的聚合结构提供统一的接口
- 需要为聚合对象提供多种遍历方法
-
JDK1.2引入的Collections就是迭代器模式
命令模式
-
概念
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
-
优点
- 降低系统耦合度,请求者和接收者之间不存在直接引用,因而实现完全解耦。相同的请求者可以对应不同的接收者,相同的接收者可以供不同的请求者使用
- 新的命令可以很容易地加入到系统中
- 可以比较容易地设计一个命令队列和宏命令
- 可以方便地实现对请求的Undo和Redo
-
缺点
- 可能会导致系统有过多的命令类
-
使用场景★★★★☆
- 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互
- 系统需要在不同的时间指定请求、将请求排队和执行请求
- 系统需要支持命令的撤销Undo和恢复Redo
-
系统需要将一组操作组合在一起,即支持宏命令
备忘录模式
-
概念
在不破坏封闭性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态
-
优点
- 提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当心的状态无效或者存在问题时,可以使用先前存储起来的备忘录将状态复原
-
缺点
- 资源消耗过大,如果类的成员变量太多,就不可避免占用大量的内存
-
使用场景★★☆☆☆
-
保存一个对象在某一时刻的状态或部分状态,这样以后需要时,它能够恢复到先前的状态
-
中介者模式
-
概念
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
-
优点
- 简化了对象之间的交互,将各同事解耦,减少子类的生成
-
缺点
- 具体d 中介者类中包含了同事之间的交互细节,可能导致终中介者类变得复杂,难以维护
-
使用场景★★☆☆☆
- 系统中对象之间存在复杂的引用关系,相互依赖关系结构混乱且难以理解
-
一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象
访问者模式
-
概念
表示一个作用于某对象中各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作
-
优点
- 使得新增访问操作变得容易
- 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散到一个个的元素类中
-
缺点
- 增加新元素类比较困难
- 破坏封装
-
使用场景★☆☆☆☆
- 一个对象结构包含很多类型的对象,希望对这些对象实施一些依赖其具体类型的操作
- 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作
解释器模式
-
概念
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
-
优点
- 易于改变和扩展文法,易于实现文法
- 增加了新的解释表达式的方式
-
缺点
- 对于复杂文法难以维护
- 执行效率较低
- 应用场景有限
-
使用场景★☆☆☆☆
- 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
- 一些重复出现的问题可以用一种简单的语言来进行表达
- 文法较为简单
- 效率不是关键问题