Swift中的设计模式:命令模式

欢迎来到一系列致力于学习设计模式的文章。 尽管许多想法与代码无关,但我们的目标是向您展示如何在Swift中实现它们(在撰写本文时为Swift 3.0)。 每个帖子彼此独立,所有项目代码都可以 在Git上找到

好的,在今天的示例中,为您的iPhone拍照,特别是在iPhone上的跳板。 您拥有一个可供用户随时点击并执行的应用程序网格。 您还有一个主页按钮可以关闭您的应用程序(好的,没有,它会将它们推送到后台,但请与我们在一起)。 每个应用程序在运行和关闭时都会运行自己的特定命令列表。

此刻,当您-iPhone-查看“天气和时钟”应用程序时,您会看到以下功能:

您如何启动应用程序? 好吧,我想您会先在WeatherApp上调用getWeatherData() ,然后再调用showWeatherAnimation()。 在ClockApp上,您只需要调用showClock()。 对于可怜的iPhone有点困惑。 两个完全不同的对象,如果没有对对象如何工作的事先了解,就无法真正知道该怎么做。

iPhone需要做的是将这些命令封装到另一个功能中,以便它知道如何启动该应用程序,而不必掌握有关该应用程序如何工作的复杂知识。 这可以通过命令模式解决。 (此示例确实是一个延伸。iPhone将使用更复杂的系统,这是现实生活,但是它提供了一个很好的视觉概念,我们可以用脑海中的所有图片来演示图案的工作原理!)

Command模式允许我们做的是将Commands转换为对象,这些对象将根据对象执行正确的功能列表,而无需修改对象本身(如果不得不询问这些对象的开发者,将是一件痛苦的事情。两个应用程序以更改其代码库)。 例如,我们将创建一个名为WeatherAppOpen的类,该类符合Command协议,并在调用通用execute()函数时执行getWeatherData()showWeatherAnimation()

这就是iPhone跳板的Command模式的UML形式:

Springboard从不与WeatherApp直接通信,因为必要的命令被抽象为通用的通用方法,这意味着Springboard只需要知道一种方法即可。

它在代码中的外观

首先,在Xcode中创建一个新项目。 我们不会在UIKit中碰任何东西,因此创建一个macOS Terminal项目。

我们将首先创建所有命令类都将遵循的Command协议。 它相对简单,仅包含Springboard将与之交谈的execute()函数。

接下来,我们将创建WeatherApp和ClockApp类。 这些类仅包含一些输出到控制台的样板方法,因此我们可以看到理论上的Springboard将会做什么。 它们将如下所示:

现在,我们需要通过Command协议访问这些方法。 为此,我们将对象创建为希望完成IE打开或关闭应用程序的Command类型。 从打开Weather应用程序开始,我们将创建WeatherAppOpenCommand

我们通过传递Weather App的实例来调用该类(如果这是现实生活,那么在iPhone中可能是Singleton,即将发布!)。 调用execute()时 ,我们随后使用对Weather App的特定命令启动该应用程序。 我们通过关闭Weather App进行相同的操作,如下所示:

开始拍照了吗? 然后,我们可以以完全相同的方式构建Clock App命令,但是调用特定于Clock App的方法:

现在,我们可以看看构建我们的假装(非常简单)的跳板。

Springboard需要能够容纳一系列打开和关闭命令(我们的应用程序)。 然后,如果有可用的应用程序,则需要能够在特定索引处执行命令。 它看起来像这样:

setCommand函数使我们能够有效地将应用程序放置在Springboard的索引处,而open / closeApp函数使我们能够在提供的索引处执行正确的命令。

因此,现在我们将构建客户端(在本例中为iPhone)。

我们创建一个Springboard实例,一个Weather App实例和一个Clock App实例。 我们使用相对于每个应用程序的打开/关闭对象来设置命令,然后将应用程序实例传递给相关命令。

运行该程序,您将获得如下所示的输出:

 获取天气数据 
 显示正确的天气动画 
 删除天气数据 
 关闭天气应用 
 显示时钟 
 删除时钟 

欢呼,您制造了iPhone *! 您正在以可扩展的封装方式运行这些应用程序,而Springboard一无所知!

山姆·斯通(@ Stonesam92)| 推特
Sam Stone(@ Stonesam92)的最新推文。 自由职业者移动开发人员和嘻哈迷。 设在曼彻斯特。… twitter.com

*我们没有制造iPhone