概述
外观模式通过一个外观类使得整个系统的接口只有一个统一的高层接口,对用户屏蔽诸多实现细节,降低用户使用成本.外观模式是我们封装api的常用手段.外观类中提供了客户端请求的简化方法和对现有系统类方法的委托调用,外观模式是一个结构型设计模式.
概述
要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,外观模式也叫门面模式,其提供了一个高层次的接口,使得子系统更易于使用
使用场景
为一个复杂子系统提供一个简单接口,子系统往往因为不断演化而变得越来越复杂,甚至可能被替换,facade模式可以提供一个简单统一的接口,对外隐藏子系统的具体实现,隔离变化.
当你需要构建一个层次结构的子系统时,使用facade模式定义子系统中每层的入口点.如果子系统之间是相互依赖的,你可以让他们仅通过facade接口通信,从而简化了他们之间的依赖关系.
UML
其中涉及到的角色有:
Facade
: 系统对外的统一接口SystemA
,System
,SystemC
: 子系统接口.
外观模式的接口比较简单,就是通过一个统一的接口对外提供服务,使得外部程序只通过一个类就可以完成系统内部的多个功能
因为隐藏了子系统的具体实现,这样即使子系统发生变化,用户也不会感知到,因为用户使用的是高层接口,隔离了变化
实例
这里我们就用手机来说明一下外观模式,
现在的手机都集合了打电话,视频聊天,拍照等功能.而不是打电话非得用一个诺基亚低端机,拍照非得用一个相机.这里的手机就相当于一个上层接口,影藏了电话,相机的实现细节,如下
- 首先,建立一个
MobilePhone
类
public class MobilePhone {
private static final String TAG = "MobilePhone";
private Phone mPhone = new PhoneImpl();
private Camera mCamera = new CameraImpl();
public void dail() {
mPhone.dail();
}
public void videoChat() {
Log.d(TAG, "videoChat: -->视频聊天");
mCamera.open();
mPhone.dail();
}
public void hangUp() {
mPhone.hangup();
}
public void takePhoto() {
mCamera.open();
mCamera.takePhoto();
}
public void closeCamera() {
mCamera.close();
}
}
其中包含了两个子系统,(拨号和拍照),MobilePhone
将这两个封装了起来,用户只需要通过MobilePhone
即可操作这两个子系统,而并不需要知道这两个子系统的调用方法.从而降低用户的使用成本.
其中的Phone
与PhoneImpl
public interface Phone {
//打电话
public void dail();
//挂断
public void hangup();
}
public class PhoneImpl implements Phone {
private static final String TAG = "PhoneImpl";
@Override public void dail() {
Log.d(TAG, "dail: --> 打电话");
}
@Override public void hangup() {
Log.d(TAG, "hangup: --> 挂断");
}
}
其中Camera
与PhoneImpl
public interface Camera {
public void open();
public void takePhoto();
public void close();
}
public class CameraImpl implements Camera {
private static final String TAG = "CameraImpl";
@Override public void open() {
Log.d(TAG, "open: -->打开相机");
}
@Override public void takePhoto() {
Log.d(TAG, "takePhoto: -->拍照");
}
@Override public void close() {
Log.d(TAG, "close: -->关闭相机");
}
}
最终的调用方法
MobilePhone mobilePhone = new MobilePhone();
mobilePhone.takePhoto();
mobilePhone.videoChat();
优缺点
优点
- 对客户端隐藏了子系统的细节,减少客户端对于子系统的耦合,做到拥抱变化
- 外观类对子系统的接口封装,使得子系统更易于使用
缺点
- 外观类接口的膨胀,由于子系统的接口都由外观类统一对外暴露,使得外观类的Api接口增多
- 外观类没有遵循开闭原则,当业务发生变更时,可能需要直接更改外观类.