Swift中的设计模式:装饰器模式

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

想象一下,您在苹果公司工作,而您要负责设计苹果网站的后端。 我们特别感兴趣的是该站点的MacBook订购功能。 尽管只有3款MacBook(在撰写本文时为MacBook,Air和Pro),但MacBook的组合数量会大大增加。

从软件设计的角度来看,用于订购过程的最明显的OOP设计风格可能是继承(多态)。 您将从基类(例如MacBook)开始,它将包含与每个MacBook相关的各种属性(即成本和说明)。 一对一的示例如下所示:

那很棒。 但是考虑一下苹果网站上实际有多少种MacBook组合? 我还没有完成数学运算,但是它必须在100年代。 按照这条路线,您将得到一个看起来像这样的设计:

它开始显得凌乱。 对于每个模型,您需要添加一个新的子类。 如果价格变动怎么办? 每个受价格变化影响的模型都需要更新,而这将变成一大堆麻烦。

装饰器模式在这里成为自己的特色。 它允许我们在运行时向对象添加其他要求。 我们可以使用用户在订购时选择的所有其他功能来“装饰”我们的基本MacBook类。 它遵循“开放-封闭”原则,即是的,对象应该是可扩展的,但不能,您不能更改现有代码(以CocoaPods为例)。

Decorator模式确实使用继承,但是以一种自然的,更有限的方式。 这样可以确保将来扩展系统不会像上图那样结束。 您仅需使用少数子类,就可以进行MacBook所需的100多种定制。

看起来像什么

装饰器模式包含一些基本组件,我们在运行时对其进行了扩展,并用装饰器类进行“装饰”。 在MacBooks的情况下,核心组件将是MacBook(在本示例中,称为MacBook Regular,以免引起混淆!),MacBook Pro和MacBook Air。 这些都将遵循相同的协议,并且能够覆盖协议中的属性,从而赋予其独立性(即,每台MacBook的成本不同)。 装饰器将从装饰器类继承,该装饰器类符合基本协议。 装饰器类包含基础组件的实例,我们将其用于将核心组件包装在装饰器中。 这是一个大致的示意图:

当我们使用MacBook示例进行总结时,您开始了解装饰器模式的工作方式:

它在代码中的外观

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

这些类都不复杂。 让我们从所有对象与以下对象交互的基本MacBook类开始:

这只是说所有符合MacBook协议的对象都应包含返回正确值类型的成本和描述项。 所有的ConcreteComponents都符合它,如下所示:

它们扩展协议属性并返回自己的值。

接下来,我们看一下MacBook Decorator。 该类符合MacBook协议,这意味着我们可以返回传递给它的MacBook对象的成本和描述。 这将是所有装饰器都继承自的类:

我们的装饰器是从此类继承的,这意味着它们能够添加自己的单独成本,并添加到传递给它的MacBook实例的描述中。 它们看起来像这样:

完善。 现在,我们要做的是模拟MacBook的自定义。 在主文件中,您将能够运行如下所示的内容:

这里所做的是从基本的MacBook开始的。 然后,我们通过遍历MacBook对象并在其上添加装饰器,并让装饰器为其添加成本和说明,从而对其进行自定义。 输出将如下所示:

 价钱:1099.0英镑,描述:MacBook 
 价钱:1598.0英镑,描述:MacBook,i7处理器 
 价钱:1897.0英镑,描述:MacBook,i7处理器,512gb SSD 
 成本:2096.0英镑,描述:MacBook,i7处理器,512GB SSD,带TouchBar 

多数民众赞成装饰图案完成! 请花一些时间来仔细阅读这一内容,因为这可能会引起混乱。 我当然不是第一次来。 和往常一样,您可以在Git上找到所有代码

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