策略模式

定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。策略模式使得算法可以独立于使用它的客户而变化。

使用情景

模型-视图-控制器中的策略模式

模型-视图-控制器中,控制器决定视图对模型数据进行显示的时机和内容。视图本身知道如何绘图,但需要控制器告诉它要显示的内容。同一个视图如果与不同的控制器合作,数据的输出格式可能一样,但数据的类型和格式可能随不同控制的不同输出而不同。因此这种情况下的控制是视图的策略。

策略模式类图

策略模式的类结构

命令模式

将请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

使用情景

命令模式允许封装在命令对象中的可执行指令。这使得在实现撤销和恢复基础设施的时候自然会选择这个模式。但这个模式的用途不只如此。命令对象的另一个为人熟知的应用是推迟调用器的执行。调用器可以是菜单项或按钮。使用命令对象连接不同对象之间的操作相当常见,比如,单击视图控制器中的按钮,可以执行一个命令对象,对另一个视图控制器进行某些操作。命令对象隐藏了与这些操作有关的所有细节。

命令模式类图

命令模式结构的类图

享元模式

运用共享技术有效地支持大量细粒度的对象

使用情景

通过享元对象能够节省的空间取决于几个因素:

  1. 通过共享减少的对象总数
  2. 每个对象内在状态(即,可共享的状态)的数量
  3. 外在状态是计算出来的还是保存的

然而,对享元对象外在状态的传递,查找和计算,可能产生运行时的开销,尤其在外在状态原本是作为内在状态来保存的时候。当享元的共享越来越多时,空间的节省会抵消这些开销。共享的享元越多,节省的存储就越多。节省直接跟共享的状态相关。如果对象有大量内在和外在状态,外在状态又能够计算出来而不用存储的时候,就能节省最大的空间。这样我们以两种方式节省了存储空间:共享减少了内在状态的开销,通过牺牲计算时间又节省了外在状态的存储空间。

享元模式类图

享元模式的类图

Flyweight是两个具体享元类ConcreteFlyweight1和ConcreteFlyweight2的父接口(协议)。每个ConcreteFlyweight类维护不能用于识别对象的内在状态instrinsicState。Flyweight声明了operation:extrinsticState方法,由这两个ConcreteFlyweight类实现。instricState是享元对象中可被共享的部分,而extrinsicState补充缺少的信息,让享元对象唯一。客户端向operation:消息提供extrinsicState,让享元对象使用extrinsicState中的独一无二的信息完成其任务。

享元模式类图2

运行时享元对象如何共享的对象图

代理模式

为其他对象提供一种代理以控制对这个对象的访问

使用情景

在iOS应用开发中,总是要关注内存的使用量。不论应用程序在何种设备上,出于性能的考虑,总是推荐懒加载技术,对开销大的数据实施懒加载,如文件系统中的大图像文件或者通过低速网络从服务器下载的大型数据。如果大开销的对象收到请求之前不需要加载,则可能过虚拟代理向客户端提供某些轻量的信息。

代理模式类图

代理模式的类图

代理模式类图2

代理模式在运行时的一种可能的对象结构

备忘录模式

在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保持这个状态。这样以后就可以将该对象恢复到原先保存的状态

使用情景

备忘录模式类图

备忘录模式结构的类图

当看管人请求Originator对象保存其状态时,Originator对象将使用其内部状态创建一个新的Memento实例。然后看管人保管Memento对象,或者把它保存到文件系统,一段时间后再把它传回给Originator对象。Originator对象不知道这个Menentor对象将如何被保存。看管人也不知道Memento对象里是什么。

备忘录模式时序图

备忘录模式的时序图

这个设计的关键是维持Memento对象的私有性,只让Originator对象访问保存在Memento对象中的内部状态(即Originator过去的内部状态)。Memento类应该有两个接口:一个宽接口,给Originator用;一个窄接口,给其他对象用。时序图中,setState:、state和init方法应该定义为私有,不让Originator和Memento以外的对象使用。