最近在学习《Objective-C编程之道:iOS设计模式解析》,本文是对外观模式的一个分析和例子实现。
例子地址:Bryanthelol/iOS_DesignPattern
里面包含书的例子。
标签:接口适配
一、外观模式是什么
外观模式为子系统中一组不同的接口提供统一的接口。
外观定义了上层接口,通过降低复杂度和隐藏子系统间的通信及依存关系,让子系统更易于使用。
类图如下:
二、外观模式用在什么情境下?
- 子系统正逐渐变得复杂
- 应用变大,演化出许多类
- 可以使用外观为这些子系统类提供一个较简单的接口
- 使用外观模式对子系统分层
- 每个子系统层级有一个外观作为入口
- 让它们通过其外观进行通信,可以简化它们之间的依赖关系
三、用代码例子讲解外观模式
这里先使用书中的一个简单例子。
有一名出租车司机,一辆车和一台计价器。
现在要使用这个出租车服务,作为一名乘客,我们只需要告诉司机我们要哪,剩下的全部事情交给司机完成。
出租车司机就是外观,而车和计价器则是子系统,供司机操作。
类图如下:
乘客使用出租车服务的唯一途径就是告诉司机去哪,而不是乘客自己按下计价器,自己踩油门换挡开车。因此我们只需要知道接口driveToLocation,传入参数“目的地”即可:
而司机CabDriver类,则会引入计价器Taximeter类和车Car类,持有它们的实例:
计价器Taximeter类和车Car类本身则定义了一系列操作的接口,供司机CabDriver类调用。
比如计价器Taximeter类有开始计价和结束计价方法:
车Car类有一些操控的方法:
这两个类的具体实现是个复杂系统,封装了能直接使用的接口。然而即使这些接口已经简化了许多,对一个只关心到达目的地的乘客来说,还是太复杂了。司机类的作用就是揽下这个活儿,无论这个子系统有多么复杂,司机类都把它们隐藏于乘客的视线之外,让乘客只看到作为外观的司机。因此,司机类CabDriver是在为出租车子系统中的其他复杂接口提供一个简化的接口。
当乘客告诉司机目的地后,在具体的实现里,司机类使用Taximeter和Car的实例来调用一系列方法,完成一次出租车服务:
到此,就是一个外观模式的简单例子。
外观模式是面向对象编程里使用得很频繁的一个模式。最经常见到的例子就是各种库里的Manager类。
比如SDWebImage,超级简化版的类图如下:
这就是典型的外观模式。特别需要注意的是子系统的分层。前面提到在什么情境下用外观模式时:
- 使用外观模式对子系统分层
- 每个子系统层级有一个外观作为入口
- 让它们通过其外观进行通信,可以简化它们之间的依赖关系
像SDWebImage这样功能全面、稍微复杂一点的库,就会产生分层的需求。这些都是在实践中需要多加思考的点。
四、总结
当程序逐渐变大变复杂时,会有越来越多小型的类从设计和应用模式中演化出来。
如果没有一种简化的方式来使用这些类,客户端代码最终将会变得越来越大、越来越难以理解,而且,维护起来会繁琐无比。
外观模式属于接口适配这个类别。接口适配类别都关注用更简单的接口或用不同的接口去适配各种接口,是面向对象编程方法里降低程序复杂度的利器。