本文首发于个人博客
前言
什么是外观模式
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
模式结构
介绍
意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
主要解决:
降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。
何时使用:
- 客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。
- 定义系统的入口。
如何解决:
客户端不与系统耦合,外观类与系统耦合。
关键代码:
在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。
应用实例:
- 去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。
- JAVA 的三层开发模式。
使用场景:
- 为复杂的模块或子系统提供外界访问的模块。
- 子系统相对独立。
- 预防低水平人员带来的风险。
注意事项:
在层次化结构中,可以使用外观模式定义系统中每一层的入口。
代码
场景
每天到公司开电脑,下班离开公司关电脑。而每次开电脑之后,都要打开Xcode、微信、QQ等等。而每次关电脑的时候,这些软件又会依次关闭。所以我们可以把这些设置为开机自启动。那么,每次开机的时候,只需要开电脑就行了,其他的我们不用关心,能自动开启。
YZComputer
创建YZComputer
类,给外界两个接口,分别是open和close
#import <Foundation/Foundation.h>
#import "YZQQ.h"
#import "YZWeChat.h"
#import "YZXcode.h"
@interface YZComputer : NSObject
-(void)close;
-(void)open;
@end
#import "YZComputer.h"
@interface YZComputer()
@property (strong, nonatomic) YZQQ * qq;
@property (strong, nonatomic) YZWeChat * weChat;
@property (strong, nonatomic) YZXcode * xcode;
@end
@implementation YZComputer
- (instancetype)init
{
self = [super init];
if (self) {
self.qq = [[YZQQ alloc] init];
self.weChat = [[YZWeChat alloc]init];
self.xcode = [[YZXcode alloc]init];
}
return self;
}
-(void)close{
NSLog(@"%s",__func__);
[self.qq close];
[self.weChat close];
[self.xcode close];
}
-(void)open{
NSLog(@"%s",__func__);
[self.qq open];
[self.weChat open];
[self.xcode open];
}
@end
YZQQ
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface YZQQ : NSObject
-(void)close;
-(void)open;
@end
NS_ASSUME_NONNULL_END
#import "YZQQ.h"
@implementation YZQQ
-(void)close{
NSLog(@"%s",__func__);
}
-(void)open{
NSLog(@"%s",__func__);
}
@end
YZWeChat
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface YZWeChat : NSObject
-(void)close;
-(void)open;
@end
NS_ASSUME_NONNULL_END
#import "YZWeChat.h"
@implementation YZWeChat
-(void)close{
NSLog(@"%s",__func__);
}
-(void)open{
NSLog(@"%s",__func__);
}
@end
YZXcode
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface YZXcode : NSObject
-(void)close;
-(void)open;
@end
NS_ASSUME_NONNULL_END
#import "YZXcode.h"
@implementation YZXcode
-(void)close{
NSLog(@"%s",__func__);
}
-(void)open{
NSLog(@"%s",__func__);
}
@end
优点:
-
对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。
-
实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。
-
降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。
-
只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。
缺点:
-
外观类接口膨胀。由于子系统的接口都有外观类统一对外暴露,使得外观类的API接口较多,在一定程度上增加了用户使用成本。
-
不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
-
在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。