金发姑娘和三种行为模式

欢迎来到我的“设计模式童话”系列的第二篇!

本系列旨在为新的编码人员(或那些没有计算机科学背景的编码人员)提供基本的设计模式简介。这些是解决常见编程问题的既定解决方案,非常有用。但是,我很难找到没有被淹死的解释。本系列旨在通过在众所周知的上下文中对它们进行解释来解决此问题-童话故事!

这篇文章将我们的奇幻冒险从创造模式转变为行为模式。虽然创建模式是创建新对象的方法,但是行为模式是使多个对象主动地共同完成复杂任务的方法。实际上,行为模式比这三个小组中的任何一个都要多,因此,我将专门发表两篇文章来涵盖所有这些内容。

在这里,我将用一个童话故事来介绍第一批行为模式,这个童话故事的主题是主人公的不良行为:金发姑娘和三只熊!

通过策略使自行车准备就绪

我们的Goldilocks版本与原始版本相似。三只熊(Papa Bear,Mama Bear和Baby Bear)煮了一些粥,然后放凉。但是在这里,我们说他们在等车时骑自行车兜风。更有趣吧?

熊们发现了他们的自行车,并意识到他们的新型号可以改变自行车的阻力。这使他们使自己的旅行变得更难或更轻松。熊们检查组成自行车的班级。

BearBike类接受熊的体重来确定阻力。但是,实际的算法不存在。为了获得抵抗力而将其传递给了自行车。

他们意识到这是策略设计模式,其中所需的算法与对象保持分离并传递。这使空手可以更好地控制自行车的阻力,使他们可以分别编写和管理算法。它们可以在这里使用,也可以在其他任何类中使用!

熊写了一些函数来获得他们想要的阻力。爸爸熊希望他的新饮食计划有更多的抵抗力。熊妈妈希望少一点,因为她从大腿疼。小熊想要减少,因为他仍在成长,而多余的一大部分由于他携带额外的旅行装备而被移除。

空头现在要做的就是创建具有各自权重和策略的类实例。自行车将使用每种策略来赋予每个熊所需的阻力。

如果熊愿意的话,它们可以使用更复杂的算法,引入其他类来根据它们的饮食,体重减轻目标甚至热量和湿度来计算阻力。所有这些逻辑都可以纳入他们的策略中,但是由于它只是传递给自行车,因此没有任何风险重叠太多,因此它们会相互破坏。像往常一样,松耦合和可维护性是设计模式的优势。

与口译员交流旅程

熊准备好了新自行车后,沿着一条路线骑自行车。爸爸熊在最前面,让他的GPS引导他们穿过树林到达海滩。熊以前从未骑过自行车到海滩,所以他们非常依赖GPS到达那里。

问题在于GPS无法选择宣布前往某个团体的路线。爸爸可以继续检查它并喊出要去的地方,但是上一次他做这件事使他分心并坠毁。因此,他编写了一个程序,使GPS为其发布新的方向。

但是GPS周围有很多数据,很难全部弄清。爸爸熊通过根据自己想要的语言将程序分解成小部分来解决此问题。他使用了Interpreter设计模式,因为它可以让他设计对象并使它们根据代码作用的语言元素一起工作。

这有点难以理解(我仍在尝试自己),所以最好在实践中看一下。

Papa Bear希望GPS发出设置为“在Y码附近转X!”的句子。第一部分是“转弯”,因此他编写了一个定义转弯的类。 GPS只能看到度数的转弯,但是Papa Bear希望将其作为基本的左,右或笔直。因此,他使用解释函数设置了Turn类,从而为他完成了这项工作。

他继续前进。这很棘手,因为有两个关于GPS如何获取距离的古怪之处:<​​/ p>

1。 GPS用来测量距离(以米为单位),而熊习惯于码。公平地说,GPS是加拿大制造的。
 2. GPS无法找到到下一弯的确切距离。它获得最小和最大距离,而熊需要找到它们之间的距离。

Papa Bear一次解决每个问题。首先,他编写了一个类,定义了距离的基本单位,该单位将米转换为码。

然后他编写了一个AverageDistance类,该类接受两个Distance实例并获取它们之间的平均距离。

现在,Papa Bear所需要的只是一堂课,该课需要一段距离和转弯,并创建GPS可以呼唤他的家人的句子。

所有这些都可以如下组合。由于我们定义了距离和转弯的语法,该语法可表达更抽象的数据,因此该语法具有表达力且易于理解。它读起来不像程序,而更像句子,其中每个对象都是单词之一。

您可以在下面查看正在运行的这些解释器对象。

这也使Papa Bear更容易跟随,因为现在熊可以安全,准确地沿路线行驶!

与访客保持稀饭

让我们谈谈童话故事中的另一个角色,金发姑娘!她一直在树林里四处游荡,看到一个陌生人的家被开着的门打开,她做着任何普通人都会做的事情,并且华而不实地吃了他们的食物。

戈尔德洛克(Goldilocks)看到三碗稀饭,但每碗都太热了,无法食用。她急于入侵他们的家,没有人有足够的时间降温!她想等到每个人都对了,但是不知道要等多久。她看着每个碗粥的代码,但惊讶于自己看到的东西。

冷却时间为0,所以根据粥类,它已经可以吃了。那没有道理!她还看到班上允许访客。她不确定这意味着什么,所以她环顾四周寻找线索。

最终,她看到一个藏在食品储藏室中的功能,名称中带有“ visitor”。它包含用于设置食物冷却时间的逻辑。

Goldilocks看到Porridge接受此访客时,会根据食物的重量将冷却时间更改为所需的时间。这行得通,但她仍然很困惑。为什么不将此逻辑直接写到类而不是此函数中呢?她最终看到了另一类像粥一样的粥。它具有与cooldownVisitor相似的属性和方法。

这有助于Goldilocks看到此访问者模式的好处。冷却逻辑需要在多个地方使用,但是使用此逻辑将两个非常不同的类扩展为一个类是不切实际的。访客提供了一个更易于管理的选项,可以将此逻辑分为其他对象并将它们传递。

使用此访问者,Goldilocks可以根据其重量创建粥实例,添加访问者并获得冷却时间。

虽然没有咖啡,但她可以想象起来看起来像咖啡的冷却时间。

添加了冷却逻辑后,她随时可以在一个陌生人的房子里吃东西!

品尝麦片粥

在稀饭冷却后,金发姑娘就可以吃了。但是,由于她饿了,她还想在陌生人家里打个a,因为为什么不呢?

Goldilocks想了解她在吃稀饭的时候何时可以入睡。她知道自己将要采取的行动-准备好粥,吃完粥,然后吃完。但是,在循环之后,访客模式刚刚向她扑来,她想清楚地了解何时准备就绪。她查阅了一些管理自己国家的代码。

对象的状态控制它可以执行或不能执行的操作,并在状态更改时对其进行调整。金发姑娘可能处于饥饿状态,无法入睡,需要先达到完全状态。她的国家决定她是否可以执行重要的事情,因此知道事情的实质很重要。

金发姑娘从建立其他国家的基类开始。这样可以确保所有国家都可以访问当前国家,下一个国家,并且可以转移到下一个国家。

她也检查了三个不同的州。仔细阅读它们,她发现自己的状态,是否可以跑步以及是否可以入睡都会影响她的思想。她还从super()参数中看到了每个状态的下一个状态。例如,从HungryState继续将其更改为EatingState。

最后,最重要的是,Goldilocks检查组成自己的Person类。

睡眠功能取决于当前状态是否允许人员睡眠。金发姑娘需要将状态更改为让她入睡的状态。她将使用nextState函数来完成此操作,该函数将移至行中的下一个State。

考虑到这一点,Goldilocks坐下来吃了一些稀饭,并根据自己的状态检查了她的行为。

她处于饥饿状态,因此她开始吃饭。这将触发nextState()并将其移至EatingState。她的思想随国家而改变,但她的睡眠能力却没有。

一旦Goldilocks吃完饭,她终于到达FullState,这改变了她的思想和睡眠行为。

管理这些状态变化很困难,但是它们确保了Goldilocks在不应该采取的行动中不采取行动。这就是为什么国家通常对于计划仅在其可以(或应该)采取行动时至关重要的原因。

还请注意,状态并不总是以这种可预测的有序方式变化。它通常取决于接收到的数据或用户输入,这可能会更加不稳定。这些通常使状态与准确数据保持同步,而视图层则是一项艰巨而至关重要的任务。

但Goldilocks在这里对此有所控制。吃饱后,她继续小睡。

使用模板测量返回路径

回到树林里,熊正走到尽头,想回头。爸爸熊检查他的地图,发现他们可以采取三种路线回家。

1。山谷小径是最简单的返回路线,但坡度较大。
 2.河滨小径的坡度更容易,但过桥会增加距离。
 3.街道路径最平坦,但在汽车周围移动会增加距离。

此外,无论他们采取什么路线,他们都需要绕过事故,绕道而行,这将增加10码。

有很多计算,虽然每次旅行的计算都是相同的,但其余的对于每个路线都是不同的。妥善管理是一项艰巨的任务。

Papa Bear意识到模板模式非常适合处理此问题。模板定义了算法的框架,因此子类可以根据需要更改步骤。这不同于策略模式,后者根据需要交换设置算法。这种模式使您可以更改算法本身的部分。

要开始,Papa Bear将创建开始模板。它会在每条路线所需的额外10码内建造。

他包括routeDistance函数,但此处未定义。这是因为每个子类都会自己定义它,以对算法进行必要的更改。

首先,我们有山谷路线。它需要将骑车距离乘以陡峭的坡度,因此非常简单。该算法的这一部分必须位于routeDistance函数中。

接下来是河滨路线。它会计算坡度,并增加20码来过桥。

最后一条是街道路线。考虑到它的轻微倾斜和在汽车周围行驶,它是最复杂的。模板模式允许它添加额外的类方法以在routeDistance中使用。

在编写所有路线后,Papa Bear要做的就是创建类实例并计算最佳路线。每个人都返回以起始模板为基础的完整算法。

看起来这条街是最好的方式!模板模式使Papa Bear可以管理每条路线的复杂性,而无需重复代码并保持每个对象之间的松散耦合。

用命令唤醒金发姑娘

随着熊回家,戈迪洛克(Goldilocks)准备入睡。但可以理解的是,她担心房屋的主人到来并感到不高兴,因为陌生人吃了饭后睡在床上。如果他们把她吓走了怎么办?她需要留下更好的方法来唤醒她。

戈尔德洛克(Goldilocks)向她报警,但担心房屋的主人不知道如何使用它,甚至不知道它的用途。她决定将如何使用警报写入命令。Command模式将有关动作的所有内容保存到单独的对象中,因此使用它的任何内容都不需要了解动作本身。他们只需要获取对象,运行execute函数,其余的操作就由set操作完成。

在入睡之前,Goldilocks会在全班检查她的闹钟。

如果有人到达,她希望他们激活quietAlarm功能。因此,她编写了一个包含警报实例的Command类,并在出现提示时执行quietAlarm。

Goldilocks现在要做的就是创建闹钟实例并将其附加到她的Command实例。

Goldilocks将此wakeGoldilocksCommand对象留在她旁边,然后进入睡眠状态。

不久之后,三只熊回到了家。他们很生气,因为粥被吃掉了,甚至还闷着某人睡在一张床上!爸爸熊正准备咆哮,但注意到女孩旁边的醒来的金发姑娘命令。Papa Bear不知道它的作用,但是由于它是Command模式,所以他不需要。具有所需动作的对象已经存储在其中,并将为他完成工作!

他迅速编写了一个类,让他可以使用此命令。

然后,他自己创建一个此类的实例,传递所找到的akeUpGoldilocks命令,然后运行wakeUpStranger函数以使用该命令。

Papa Bear发现自己伸手去拿一个陌生的钟,然后发出安静的警报。金发姑娘从小睡中轻轻醒来,看到了熊,然后尖叫着从房子里跑了出来。熊耸了耸肩,从此以后他们过着幸福的生活。

设计模式探索继续

这篇文章标志着这个设计模式和童话故事系列的中途。在此过程中,仍然存在其余的行为和结构模式。但是不久我们将杀死设计模式巨龙,并将编程公主保存在编码公司的城堡里!