门面模式是一种结构模式,为复杂的系统提供一个简单的接口。它涉及两种类型。
门面提供简单的方法来与系统交互。这允许消费者使用门面,而不是了解和与系统中的多个类进行交互。
依赖性是由门面拥有的对象。每个依赖对象执行一个复杂任务的一小部分。
只要你有一个由多个组件组成的系统,并希望为用户提供一个简单的方法来执行复杂的任务,就可以使用这种模式。
例如,一个产品订购系统涉及几个组件:客户和产品、库存、运输订单和其他。
与其要求消费者了解这些组件中的每一个,以及它们是如何相互作用的,你可以提供一个门面来展示常见的任务,如下达和完成一个新订单。
打开Starter目录下的IntermediateDesignPatterns.xcworkspace,然后打开Facade页面。
你将实现上面提到的订货系统的一部分。具体来说,你将创建一个允许用户下订单的OrderFacade。
在代码示例后输入以下内容。
接下来,在playground的末尾添加以下内容。
首先,你声明InventoryDatabase。这是一个简化版的数据库,用于存储可用库存,它代表了一个给定产品的可用物品的数量。
你还要声明ShippingDatabase。这同样也是一个简化版的数据库,它保存着待发货量,代表着已经被订购但尚未为某个客户发货的产品。在一个复杂的系统中,你很可能还要定义一个CustomerDatabase、BillingDatabase等等。然而,为了保持这个例子的简单,你将省略这些元素。
在playground的末尾添加以下内容。
在这里,你声明了OrderFacade,并添加了两个属性:inventalDatabase和shippingDatabase,你通过其初始化器init(inventalDatabase:shippingDatabase:)将这两个属性传入其中。
接下来,在你刚刚添加的OrderFacade类的末尾添加以下方法。
这是一个简单的方法,门面的消费者将调用这个方法来为给定的产品和客户下订单。
以下是代码的内容。
你首先将产品名称和客户名称打印到控制台。
在执行订单之前,你要确保在inventoryDatabase.inventory中至少有一个指定的产品。如果没有,就打印该产品缺货。
由于至少有一种产品可用,你就可以完成订单。这样,你就把inventoryDatabase.inventory中的产品数量减少了一个。
然后,你将该产品添加到shippingDatabase.pendingShipments中,用于给定客户。
最后,你打印出该订单已成功下达。
很好,你已经准备好试一试这个门面了! 在playground的最后添加以下代码。
下面是这个的作用。
首先,你设置两个产品。 rayDoodle是Ray的画,vickiPoodle是Vicki的珍贵宠物贵宾犬。甚至不要让我开始讨论狮子狗的涂鸦!这是很重要的。
接下来,你用这些产品创建inventoryDatabase。有很多rayDoodles(他喜欢涂鸦,显然),只有一个vickiPoodle。这毕竟是她珍爱的贵宾犬!
然后,你使用库存数据库和一个新的运输数据库。
最后,你创建一个客户并调用orderFacade.placeOrder(for:by:)。
当然,你的订单是为Vicki的珍贵的狮子狗准备的。它很贵,但它是值得的!
你应该看到以下内容打印到控制台。
Place order for 'Vicki's prized poodle' by 'Johnny Appleseed'
Order placed for 'Vicki's prized poodle' by 'Johnny Appleseed'
撇开贵宾犬和卷毛狗不谈,你刚刚为一个订购系统创造了一个良好的开端!你应该注意什么?
小心创建一个知道你的应用程序中每一个类的 "神 "面孔。
为不同的使用情况创建多个facade是可以的。例如,如果你注意到一个facade有一些类使用的功能和其他类使用的功能,可以考虑把它拆成两个或更多的facade。
你将继续上一章的Mirror Pad应用。
如果你跳过了上一章,或者你想重新开始,请打开Finder并导航到你下载本章资源的地方。然后,在Xcode中打开starter/MirrorPad\MirrorPad.xcodeproj。
你将在本章中实现一个分享按钮,并使用一个facade。为了将重点放在设计模式上,同时也为了节省你的输入,我们为你提供了facade的依赖关系。
打开Finder,导航到你下载本章资源的地方。在Starter和Final目录旁边,你会看到一个Resources目录,其中包含DrawingSelectionViewController.swift, DrawingSelectionViewController.xib和ImageRenderer.swift。
将Finder窗口置于Xcode上方,并将DrawingSelectionViewController.swift和ImageRenderer.swift拖到 应用程序的Facades组。
当出现提示时,如果需要的话,勾选复制项目的选项,然后按完成来添加文件。
最后,将DrawingSelectionViewController.xib拖入视图组。同样,如果需要的话,选择复制项目,然后按完成来添加文件。
你将使用DrawingSelectionViewController在现有的ViewController上显示一个轮廓视图。它有一个按钮可以在inputDrawView和wholeDrawView之间切换选中的绘图,还有一个 "分享 "按钮可以分享选择。
你将把选中的视图传递给ImageRenderer,将其转换为UIImage。然后你将使用生成的图像来创建一个UIActivityViewController。
UIActivityViewController实际上是一个苹果提供的facade! 它提供了一个简单的接口,用于与iCloud、iMessage、Twitter和设备上的其他应用程序分享字符串、图片和其他媒体。
你的工作是创建一个名为ShareFacade的新界面。你将用它来提供一个简单的界面,让消费者选择要分享的视图,把视图变成图片,并通过用户选择的任何应用程序进行分享。
因此,ShareFacade将在DrawingSelectionViewController、ImageRenderer和UIActivityViewController之间进行协调以完成这一目标。
你已经得到了任务简介,所以现在是时候写代码了
在应用程序的Facades组中创建一个名为ShareFacade.swift的新Swift文件,并将其内容替换为以下内容。
让我们来看看这里发生了什么。
首先,你为wholeDrawing、inputDrawing和parentViewController声明实例变量。为了防止强引用循环,你把每个属性都表示为无主属性。
接下来,你为imageRenderer声明一个属性,你将在后面使用它。
接下来,你创建一个初始化器来设置每个不属于你的属性。
最后,你为presentShareController建立了一个方法,最终消费者将调用该方法来呈现共享控制器,以选择要共享的视图,将视图转换为图像并共享。
在你实现presentShareController()之前,你需要让ShareFacade符合DrawingSelectionViewControllerDelegate,这是DrawingSelectionViewController所要求的。
还是在ShareFacade.swift中,在关闭类的大括号后的文件底部添加以下内容。
每当用户按下 "取消 "按钮放弃共享时,drawingSelectionViewControllerDidCancel就被调用。按下 "取消 "按钮来终止共享。在这种情况下,你告诉parentViewController用一个动画来解散它当前显示的视图控制器。
drawingSelectionViewController(_:didSelectView:)被调用,每当用户按下分享按钮来选择时。
用户按下 "分享 "按钮选择要分享的视图时,就会调用drawingSelectionViewController(_:didSelectView:)。在这种情况下,你首先告诉parentViewController在没有动画的情况下解除其当前视图控制器。
接下来,你立即从给定的视图中创建一个图像,将其传递给imageRenderer。
反过来,你用这个视图来创建一个UIActivityViewController,由parentViewController用动画来呈现。
最终,这将产生一个很好的效果,即立即隐藏DrawingSelectionViewController,并在新的UIActivityViewController中播放动画。
接下来,在presentShareController()中添加以下代码。
这段代码相当简单明了。
你首先创建一个新的DrawingSelectionViewController实例,名为selectionViewController的实例,使用一个方便的类构造方法createInstance(wholeDrawing:inputDrawing:delegate)。
如果你检查DrawingSelectionViewController.swift中的这个方法,你会看到它通过调用DrawingSelectionViewController(nibName: nil, bundle: nil)创建一个新的视图控制器实例,设置modalPresentationStyle和modalTransitionStyle,将传入的变量作为新实例的属性,并返回视图控制器。
最后,你告诉parentViewController用一个动画来呈现selectionViewController。
你的ShareFacade已经设置好了,可以开始使用了!
打开ViewController.swift,在开头的类大括号后添加以下内容。
在这里,你创建了一个名为shareFacade的新属性。因为你把self作为parentViewController,所以你把它变成一个懒惰的属性,以确保ViewController本身首先被完全创建。
最后,在sharePressed(_:)中添加以下内容。
shareFacade.presentShareController()
通过这一行,你已经为ViewController添加了共享功能。Facades不是很好吗?
构建并运行该应用程序。在左上角的视图中画几条线,按下分享按钮,你就会看到DrawingSelectionViewController。
按下红色的分享按钮,你会看到UIActivityViewController,在这里你可以选择一个应用来分享图片。
如果你使用的是模拟器,你将只看到几个可用的应用程序。如果你使用真实的设备,你会看到更多的应用程序,这取决于你所安装的应用程序。
你在本章中了解了门面模式。下面是它的关键点。
Facade模式为复杂的系统提供了一个简单的接口。它涉及两种类型:门面和它的依赖关系。
门面提供简单的方法来与系统交互。在幕后,它拥有并与它的依赖关系互动,每个依赖关系执行复杂任务的一小部分。
Mirror Pad已经有了长足的进步,代码的可维护性也大大提高了 还有很多功能你可以添加。
颜色和笔触选择
撤销和重做功能
在应用程序中保存和加载绘图
这些都可以使用你在中级和基本设计模式部分学到的现有模式。你可以随心所欲地继续构建Mirror Pad。
但你还有更多的学习要做。继续学习下一节,了解高级设计模式,包括mediator、composite、command等。
祝贺你走到了中级部分的结尾! 如果你已经完成了到目前为止的所有章节,你现在知道了iOS中使用的大部分设计模式。
上一章 | 目录 | 下一章 |
---|