重新思考Swift中的设计模式:状态模式

本文展示了如何在Swift中实现State模式,利用Swift的强大功能使实现更简单,更灵活。我们通过一个例子来探索状态模式的各个方面,并评估其处理需求变化的能力。然后,我们将了解关键实现注意事项以及模式的优点和实际应用。

有限状态自动机

真实世界域通常包含可以在任何时间点处于有限数量的可能状态之一的实体。根据实体所处的状态,它可能对同一个动作或事件的反应不同。

考虑一个典型的自动售货机。当没有插入钱时,按下应该销售特定项目的按钮无效。这是因为机器未处于执行该操作的正确状态。即使插入了钱,机器也可以出售一些物品而不是其他物品,这取决于插入了多少钱以及每件物品的成本。一旦给出了支付的物品,机器就会回到不收钱的状态下卖掉的东西。

可以使用有限状态自动机或有限状态机有效地对这些类型的实体进行建模。有限状态自动机或有限状态机,或简称为状态机,是一种抽象机器,可以处于有限数量的状态中的任何一个状态,并且可以响应于某些触发事件在这些状态之间转换。

可以使用条件语句(通常是嵌套的switch语句)在代码中实现简单状态机。对于非常简单的状态机实现,这可能是足够的,并且非常有效。但是,这种方法不能很好地扩展。在处理更复杂的状态机时,它可能导致代码繁琐,难以理解且难以维护。

状态模式是实现状态机的强大且可扩展的方式。特定于状态的行为由各种状态类型封装,被建模的实体将事件和操作委托给它们。管理国家之间转换的规则也可以由州自己管理。

状态模式

1. 定义

状态模式允许类型的实例通过其内部状态的更改来更改其行为。从外部角度来看,实例可能会改变其类型。

2. 结构与参与者

下面的类图说明了State模式的结构:

Context类型定义客户端使用的接口。抽象状态类型反过来定义了一个由Context使用的接口,该接口封装了Context的特定于状态的行为。每个具体的State类型实现与Context的特定状态相关联的行为。因此,Context能够将特定于州的行为委托给具体的State类型。

模式的灵活性来自于Context仅依赖于抽象State类型而不依赖于任何具体State类型的事实。因此,当Context从一个状态转换到另一个状态时,可以交换具体状态类型的实例。

状态机图

状态机图或状态图是可视化状态机的好方法。每个状态由圆角矩形表示,连接矩形的箭头表示状态之间的转换。如果状态机具有默认初始状态,则使用小的实心圆来表示初始伪状态,其通常自动转换到第一适当状态。

让我们假设我们的任务是为安全系统构建控制单元,当存在入侵或入侵威胁时,它会发出警报。安全系统将连接到传感器,每个传感器都可以检测到漏洞,例如正在打开的门或窗户。当系统布防时,这种违规行为应该引起警报。该系统还将具有一个或多个应急开关,即使没有实际的突破也可用于发出警报,但可能存在潜在入侵者的突然威胁。当系统未布防时,违规或恐慌信号不应起作用。

我们还需要确保一旦武装起来,只能通过使用代码解除系统的武装。系统初始化时将设置此代码,并且必须用于撤防系统。同样的代码也必须用于重置系统,即一旦发出警报就停止警报。

如果我们将上述安全系统视为状态机,我们可以通过以下状态图直观地表示它:

虽然该图非常直观,但是根据统一建模语言(UML)规范,让我们简要地看一下它的组成部分和一些管理状态图构造的形式。

1. 状态,事件和过渡

我们的系统可以处于以下三种状态中的任何一种:解除武装,武装和警报。 Disarmed状态是默认的初始状态。

状态之间的转换可能由以下事件引起:

  • 手臂:仅适用于撤防状态。导致转换到武装状态。
  • 解除武装:仅适用于武装状态。导致转换到撤防状态。
  • 违反:表示传感器已被破坏。仅适用于武装状态。导致转换到警报状态。
  • 恐慌:表示已激活紧急切换。仅适用于武装状态。导致转换到警报状态。
  • 重置:仅适用于警报状态。导致转换到撤防状态。

2. 各个状态的进入退出活动

状态机中的任何状态都可以具有进入和退出活动。在输入状态之后执行输入活动,而在退出状态之前执行退出活动。为状态指定活动不是强制性的,但它是确保状态封装与其关联的行为的有用方法。在我们的示例中,每个州都有一个条目活动,而只有警报状态有一个退出活动。

3. 保证条件和过渡效果

转换的完整规范可以包含四个部分 - 事件,保护条件,效果和目标状态。事件是触发转换的事件,目标状态是在转换完成时变为活动状态。保护条件是一个布尔表达式,它被计算并且仅当表达式求值为true时才会触发转换。效果是在转换完成之前(即,在目标状态变为活动之前)执行的可选活动。

转换标签可以包括事件,保护条件和效果,格式为:'event [guard condition] / effect'。在我们的示例中,两个转换具有保护条件。这些确保只能使用有效代码撤防和重置系统。我们在示例中的任何转换中都没有使用效果。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容