前言
比方说今天不想开车,于是打电话叫了出租车。只要出租车能把你送到目的地,你会对出租车说的第一句话是"送我去 xxx"。然后出租车司机就开始执行一系列的 “动作”(松刹车,踩油门等)。出租车司机抽象走了驾驶汽车的底层复制操作的细节,他通过提供驾驶服务(简化了的接口),把你与原本复杂的车辆操作接口分离开来,这种方式称为外观模式。
什么是外观模式
外观模式(Facade Pattern)为子系统中的一组接口提供一个一致的界面,外观模式在客户端和复杂系统之间定义了一个上层接口,解决了客户端与系统耦合,通过降低复杂度和隐藏子系统之间的通信及依存关系,使得这一子系统更加容易使用。
一个外观实现的示例结构图.png什么时候使用外观模式
- 客户端不需要知道系统内部的复杂联系,为复杂的模块或子系统提供外界访问的模块。
- 子系统相对独立,定义其入口。
外观模式的优缺点
外观模式的优点
- 减少系统相互依赖。
- 提高灵活性。
- 提高了安全性。
外观模式的缺点
不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
外观模式的实现
回到出租车的例子,有一辆出租车,其出租车司机为驾驶出租车的一组复杂接口提供了一个简化的接口。整个出租车服务作为一个封闭系统,包含一名出租车司机,一辆车和一台计价器。乘客和出租车系统交互的唯一途径就是通过向出租车司机发送 driveToLocation:x
消息。
-
Car
定义了几个动作,如releaseBrakes
(松刹车)、changeGears
(换档) 等等。
@interface Car : NSObject
- (void) releaseBrakes;
- (void) changeGears;
- (void) pressAccelerator;
- (void) pressBrakes;
- (void) releaseAccelerator;
// ...
@end
@implementation Car
- (void) releaseBrakes{}
- (void) changeGears{}
- (void) pressAccelerator{}
- (void) pressBrakes{}
- (void) releaseAccelerator{}
@end
-
Taximeter
定义了两个事件,start
(开始)和stop
(停止)
@interface Taximeter : NSObject
- (void) start;
- (void) stop;
@end
@implementation Taximeter
- (void) start{}
- (void) stop{}
@end
-
CarbDriver
作为 "外观" 以简化接口@interface CabDriver : NSObject - (void) driveToLocation:(CGPoint) x; @end @implementation CabDriver - (void) driveToLocation:(CGPoint) x { // ... // set off the taximeter Taximeter *meter = [[Taximeter alloc] init]; [meter start]; // operate the vehicle // until location x is reached Car *car = [[Car alloc] init]; [car releaseBrakes]; [car changeGears]; [car pressAccelerator]; // ... // when it's reached location x // then stop the car and taximeter [car releaseAccelerator]; [car pressBrakes]; [meter stop]; // ... } @end
总结
当程序逐渐变大变复杂时,会有越来越多小型的类从设计和应用模式中演化出来。如果没有一种简化的方式来使用这些类,客户端代码最终变得越来越大,越来越难以理解,而且维护起来会繁琐无趣。外观有助于提供一种更为简洁的方式来使用子系统中的这些类。处理这些类的默认行为的,只是定义在外观中的一个简单的方法,而不必直接去使用这些类。
网友评论