试想这种情况,用户添加了一条记录,为了保持本地和服务器数据的一致性,除了在本地数据库插入记录,还需要把该记录发送给服务器,让服务器的数据库也一并更新。
为了保持代码的可读性和低耦合性,一般会把不同的功能放在不同的文件不同的类中。如上面所说的情况,就需要一个DataHandler类更新本地数据库,还需要一个NetworkClient类处理网络请求。这两个类有如下定义:
@interface DataHandler : NSObject
- (void)addItemToDatabase:(id)item;
@end
@interface NetworkClient : NSObject
- (void)addItemToServer:(id)item;
@end
每当数据有变化,都需要调用这两个类的方法。如果DataHandler和NetworkClient这两个类中的方法有变化,相应的需要修改很多调用者的代码。
而采用外观模式时,一个Facade将DataHandler和HTTPClient封装在一起,然后提供一个新的接口。 现在定义一个Manager类如下:
@interface Manager : NSObject
- (void)addItem:(id)item;
@end
@implementation Manager
{
DataHandler *dataHandler;
NetworkClient *networkClient;
}
- (void)addItem:(id)item
{
[dataHandler addItemToDatabase:item];
[networkClient addItemToServer:item];
}
@end
现在每当用户添加新数据时,只需调用Manager的addItem:方法就可以实现本地和服务器数据库的操作。而且如果DataHandler类和NetworkClient类的方法有变化,也只需修改Manager中的代码,对调用者并没有影响。
外观模式本质就是一种封装,将零散的功能组合成一个,然后对外提供一个接口,使用者只需要知道这一个接口就可以了。这种模式大大降低了代码的耦合性,对代码重用和迭代开发很有帮助。
注意,在使用外观模式时,各个子模块的接口是无法被隐藏起来的,你也不能阻止调用者不使用集成的API而去单独访问各子模块接口。