外观设计模式
外观设计模式向复杂的子系统提供了简单的接口,相比将一系列的类和他们的接口暴露给用户,你只需要暴露一些简单的未定义的API。
接下来的图片解释了这一概念。
使用这些API接口的人完全没有意识到你这下面隐藏的复杂性,在有一系列类,特别是他们使用很复杂或者难以理解的时候,这个模式是非常好的。
外观设计模式使用从接口层面去使用,在实现技术上隐藏而将代码解藕了。它也减少了你外部的代码对于内部子系统代码的依赖性。它在外观模式可能要进行
改变的情况下也是很有用的,因为外观的类仍然可以保持相同的API当背后的情况发生了变化时。比如,有一天你想改变背后的服务代码,你不用去改变这些代码
因为这些API不会改变。
如何使用外观设计模式
目前你有PersistencyManager类去本地保存album的数据,而HTTPClient去处理远程的数据交流。工程里面的其他代码不应该意识到这个逻辑。
要实现这个LiabraryAPI你应该hold住PersistencyManager和HTTPClient的一个实例。然后LiabraryAPI会暴露一个简单的接口去访问这些服务。
小贴士:通常一个单例会在app的整个生命周期都会存在,你不应该持有过多的单例指针指向其他物体,因为它们在app关闭之前不会被释放。这个设计应该是像下面的这个图这样。
LiabraryAPI 会暴露给其他代码,但是会隐藏PersistenceManager和HTTPClient针的复杂性。
打开LiabraryAPI.h,添加#import “album.h”,接下来添加这些方法的人声明到里面。
- (NSArray *)getAlbums; - (void)addAlbum:(Album *)album atIndex:(int)index; - (void)deleteAlbumAtIndex:(int)index;
从现在开始,这些方法将会被你暴露给外部使用。
打开LiabraryAPI.m文件。加入
#import "HTTPClient.h" #import "PersistencyManager.h"
这是你导入这些类唯一的地方,记住:你的复杂的系统只能由你的API唯一的访问。现在,添加这些私有变量通过类扩展。(在@implementation上方)。
@interfaceLibraryAPI () { HTTPClient *client; PersistencyManager *manager; BOOL isOnLine; }
isOnline决定了服务器石油应该根据album表中的变化进行更新,例如添加或者删除albums.
你需要在init里面对它们进行初始化。在LiabraryAPI.m文件中添加下面代码:
-(id)init { if (self = [superinit]) { client = [[HTTPClientalloc]init]; manager = [[PersistencyManageralloc] init]; isOnLine = NO; } returnself; }
HTTPClient这个并不会真正的和一个服务器配合工作,在这里只是为了演示外观设计模式,所以isOnline总是NO。接下来在LiabraryAPI.m文件中添加这些方法。
-(NSArray *)getAlbums { return [managergetAlbums]; } - (void)addAlbum:(Album *)album atIndex:(int)index { [manageraddAlbum:album atIndex:index]; if (isOnLine) { [clientpostRequest:@"/api/addAlbum"body:[album description]]; } } - (void)saveAlbums { [managersaveAlbums]; } - (void)deleteAlbumAtIndex:(int)index { [managerdeleteAlbumAtIndex:index]; if (isOnLine) { [clientpostRequest:@"/api/deleteAlbum"body:[@(index) description]]; } }
看一下这个
- (void)addAlbum:(Album *)album atIndex:(int)index
方法,这个类首先本地更新数据,然后如果由网络连接,就远程更新,这就是外观模式的魅力,如果在你系统以外的类加入了一些新的album,它不知道,也不需要去知道,这些复杂性都被隐藏在下面了。
提醒:当为你的子系统中的类设计一个外观模式,记住没有什么做什么去阻止客户端去直接访问这些隐藏的属性,不要假设所有的外部客户端都需要向你在外观模式下使用它们的方法那样去使用它们。
编译和运行你的程序,你会看见如下的空白的黑色屏幕。
你需要做点事情去在屏幕上去显示album的数据-那就是接下来的下一个设计模式:装饰设计模式。Decorator.