设计模式读书笔记(九)

"Head First 设计模式第十章"

Posted by jhljx on January 29, 2018

目录

1. 状态模式

状态模式

策略模式和状态模式是双胞胎,在出生时才分开。

策略模式是围绕可以互换的算法来创建成功业务的。然而,状态模式通过改变对象内部的状态来帮助对象控制自己的行为。

之前的代码一直用if条件语句来判断状态并且完成状态的转移,但是随着业务的变化,这种写法的局限性也越来越强。

新的设计需要做如下的事情:

  • 首先,定义一个State接口。在这个接口内,糖果机的每个动作都对应一个方法。
  • 然后为机器中的每个状态实现状态类。这些类负责在对应状态下进行机器的行为。
  • 最后,我们要摆脱旧的条件代码,取而代之的方式是,将动作委托到状态类。

新的设计通过结构上改变实现,做到了以下几点:

  • 对每个状态的行为局部化到它自己的类中。
  • 将容易产生问题的if语句删除,以方便日后的维护。
  • 让每一个状态“对修改关闭”,让糖果机“对扩展开放”,因为可以加入新的状态类
  • 创建一个新的代码基和类结构,这更能映射万能糖果公司的图,而且更容易阅读和理解。

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

状态模式的类图

策略模式和状态模式的类图是一样的。这两个模式的差别在于它们的“意图”。

以状态模式而言,我们将一群行为封装在状态对象中,context的行为随时可委托到那些状态对象中的一个。随着时间的流逝,当前状态在状态对象集合中游走改变,以反映出context内部的状态,因此,context的行为也会跟着改变。但是context的客户对于状态对象了解不多,甚至根本是浑然不觉。

以策略模式而言,客户通常主动指定context所要组合的策略对象是哪一个。现在,固然策略模式让我们具有弹性,能够在运行时改变策略,但对于某个context而言,通常都只有一个最适当的策略对象。

我们把策略模式想成是除了继承之外的一种弹性替代方案。如果你使用继承定义了一个类的行为,你将被这个行为困住,甚至要修改它都很难。有了策略模式,你可以通过组合不同的对象来改变行为。

我们把状态模式想成是不用在context中放置很多条件判断的替代方法。通过将行为包装进状态对象中,你可以通过在context内简单地改变状态对象来改变context的行为。

状态模式中的状态类也可以被多个context实例共享。

将状态转换放在状态类中的缺点是:

  • 状态类之间产生了依赖
  • 通常会导致设计中类的数目大量增加

在状态模式中,客户不会直接和状态进行交互,状态是用在context中来代表它的内部状态及行为的。所以只有context才会对状态提出请求,而客户不会直接改变context的状态。

状态模式和策略模式简单对比:

  • 状态模式和策略模式有相同的类图,但有着不同的意图
  • 状态模式允许context随着状态的改变而改变行为
  • 策略模式通常会用行为或算法来配置context类

在之前的实现中,我们使用interface来实现State类,但是我们也可以把State设计成抽象类,把方法的默认行为放在其中。

  • 状态模式:封装基于状态的行为,并将行为委托到当前状态
  • 策略模式:将可以互换的行为封装起来,然后使用委托的方法,决定使用哪一个行为
  • 模板方法:由子类决定如何实现算法中的某些步骤

OO 原则

  • 封装变化
  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程
  • 对交互对象之间的松耦合设计而努力
  • 类应该扩展开放,对修改关闭
  • 依赖抽象,不要依赖具体类
  • 类应该只有一个改变的理由