Kevin's Code
Talk is cheap, show me the code!

iOS设计模式之外观模式(Facade)

Jan 13, 2015
有些地方外观模式也被叫做门面模式,英文即Facade Pattern,提前说明一下。

试想这种情况,用户添加了一条记录,为了保持本地和服务器数据的一致性,除了在本地数据库插入记录,还需要把该记录发送给服务器,让服务器的数据库也一并更新。

为了保持代码的可读性和低耦合性,一般会把不同的功能放在不同的文件不同的类中。如上面所说的情况,就需要一个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而去单独访问各子模块接口。