【推荐】【老外写的iOS设计模式系列】第3部分 门面模式

由 @krq_tiger( http://weibo.com/xmuzyq )翻译,如果你发现有什么错误,请与我联系谢谢。
门面(Facade)模式(译者注:facade有些书籍译为门面,有些书籍译为外观,此处译为门面


 
门面模式针对复杂的子系统提供了单一的接口,不需要暴漏一些列的类和 API 给用户,你仅仅暴漏一个简单统一的 API
下面的图解释了这个概念:

 

这个 API 的使用者完全不需要关心背后的复杂性。这个模式非常适合有一大堆很难使用或者理解的类的情况。
门面模式解耦了使用系统的代码和需要隐藏的接口和实现类。它也降低了外部代码对内部子系统的依赖性。当隐藏在门面之后的类很容易发生变化的时候,此模式就很有用了,因为当背后的类发生变化的时候,门面类始终保持了同样的 API
举个例子来说,如果有一天你想取代后端服务,你不需要改变 API 的使用者,因为 API 没有发生变化。

如何使用门面模式
当前你已经用 PersistencyManager 本地保存专辑数据,使用 HTTPClient 处理远程连接,工程中的其它类暂时与本次实现的逻辑无关。
为了实现这个模式,只有 LibraryAPI 应该保存 PersistencyManager HTTPClient 的实例,然后 LibraryAPI 将暴漏一个简单的 API 去访问这些服务。

 

注意 :  通常来说,单例类的生命周期贯穿于整个应用的生命周期中,你不应对保存太多其它对象的强引用,因为他们只有到应用关闭的时候才能被释放。
本次设计看起来像下图:


LibraryAPI 将暴漏给其它代码,但是它隐藏了 HTTPClient PersistencyManager 的复杂性。
打开 LibraryAPI.h ,在文件头部增加下面的导入语句:
#import "Album.h"  
接下来,在 LibraryAPI.h 中增加如下的方法定义:
- (NSArray*)getAlbums;  
- (void)addAlbum:(Album*)album atIndex:(int)index;  
- (void)deleteAlbumAtIndex:(int)index;  
目前有一些你需要暴漏给其它类的方法。
打开 LibraryAPI.m ,增加如下的两个导入语句:
#import "PersistencyManager.h"  
#import "HTTPClient.h"  
这里将是唯一的导入这两个类的地方。记住:你的 API 是对于复杂系统唯一的访问点。
现在,增加通过类扩展( class extension )增加一些私有的变量(在 @implementation  行之上) :
@interfaceLibraryAPI () {  
    PersistenceManager *persistencyManager;  
    HTTPClient *httpClient;  
    BOOL isOnline;  
}  
@end  
isOnline 决定了是否服务器中任何专辑数据的改变应该被更新,例如增加或者删除专辑。
你现在需要通过 init 初始化这些变量。在 LibraryAPI.m 中增加如下的代码:
- (id)init{  
    self = [super init];  
    if (self) {  
        persistencyManager = [[PersistenceManager alloc] init];  
        httpClient = [[HTTPClient alloc] init];  
        isOnline = NO;  
    }  
    return self;  
}  
HTTP  客户端实际上不会真正的和一个服务器交互,它在这里仅仅是用来演示门面模式的使用,所以 isOnline 将总是 NO
接下来,增加如下的三个方法到 LibraryAPI.m:
-(NSArray*)getAlbums  
{  
    return [persistencyManager getAlbums];  
}  
  
- (void)addAlbum:(Album*)album atIndex:(int)index  
{  
    [persistencyManager addAlbum:album atIndex:index];  
    if (isOnline)  
    {  
        [httpClient postRequest:@"/api/addAlbum" body:[album description]];  
    }  
}  
  
- (void)deleteAlbumAtIndex:(int)index  
{  
    [persistencyManager deleteAlbumAtIndex:index];  
    if (isOnline)  
    {  
        [httpClient postRequest:@"/api/deleteAlbum" body:[@(index) description]];  
    }  
} 
我们来看一看 addAlbum:atIndex:. 这个类首先更新本地的数据,然后如果有网络连接,它更新远程服务器。这就是门面模式的强大之处。当某些外部的类增加一个新的专辑的时候,它不知道也不需要知道背后的复杂性。

 

注意 : 当为子系统的类设计门面的时候,要记住:任何东西都不能阻止客户端直接访问这些隐藏的类。不要对这些防御性的代码太过于吝啬,并且也不要假设所有的客户端都会和门面一样使用你的类。
构建并运行你的应用。你将看到一个激动人心的空白的黑屏(哈哈) :

 



 

 

接下来,你将需要在屏幕上显示专辑数据,使用你的下个设计模式 - 装饰器设计模式将是非常好的选择。

原文出处:http://xmuzyq.iteye.com/blog/1942379
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值