什么是外观模式?
外观模式也叫门面模式(Facaed Pattern)。
要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。从而提供一个统一的高层接口,使得子系统更易于应用。其实外观模式是最常用到的,比如我们Android中有Toast.makeText(MainActivity.this, “Hello,World!”, Toast.LENGTH_SHORT).show();我们
只需要传递其中需要的参数,并不需要知道他是显示到屏幕上具体步骤,系统已经对他做好了封装。
外观模式的适用场景
简单接口访问系统复杂逻辑内容
耦合度高、复杂的系统
外观模式用例
比如现在我们的手机集成了拍照、电话、GPS定位等功能,现在呢我们需要实现视频通话,或者单纯的打电话。经过分析,需要的有拍照功能、GSM通话等,其实按功能来分我们需要(假如设备功能单一)一部可以通话的电话、一个电脑用来上网、一个摄像头等。而手机只是把这些功能集中在一体上,使用更方便。说了这些,只是想说明外观模式针对的对象是多元化的,并不是类似手机这个单一对象,这里手机只是集成了这些功能。
UML用例图
MobilePhone类
public class MobilePhone {
private ICamera mCamera = new CameraImpl();
private IPhone mPhone = new PhoneImpl();
public void dailNumber(){
mPhone.dailNumber();
}
public void videoChat(){
mCamera.openCamera();
mPhone.dailNumber();
System.out.println("视频通话已建立");
}
public void hangUp(){
mPhone.hangUp();
}
public void takePhoto(){
mCamera.openCamera();
mCamera.takePhotos();
}
public void closeCamera(){
mCamera.closeCamera();
}
}
IPhone接口类
public interface IPhone {
public void dailNumber();
public void hangUp();
}
PhoneImpl实现类
public class PhoneImpl implements IPhone {
@Override
public void dailNumber() {
System.out.println("正在打电话。。。");
}
@Override
public void hangUp() {
System.out.println("电话已挂断。。。");
}
}
ICamera接口类
public interface ICamera {
public void openCamera();
public void takePhotos();
public void closeCamera();
}
CameraImpl实现类
public class CameraImpl implements ICamera {
@Override
public void openCamera() {
System.out.println("相机已打开。。。");
}
@Override
public void takePhotos() {
System.out.println("正在照相。。。");
}
@Override
public void closeCamera() {
System.out.println("相机已关闭。。。");
}
}
主类调用
public class Test {
public static void main(String[] args) {
MobilePhone phone = new MobilePhone();
//视频聊天
phone.videoChat();
System.out.println("----------");
//照相
phone.takePhoto();
}
}
运行结果:
相机已打开。。。
正在打电话。。。
视频通话已建立
----------
相机已打开。。。
正在照相。。。
总结
外观模式是一个高频使用的设计模式,贯穿整个模式的是封装的使用,通过封装减少用户操作来实现预期功能,减少用户使用成本,也能提高系统的灵活性。好比我们使用takePhotos功能用户不需要去操作监测相机状态、打开相机、监测内存状态等功能,这些可以有系统封装起来,对于用户只需要调用takePhotos一个方法就可以了。是不是类似于迪米特(最少知道)法则。
优点:
对客户端隐藏了实现细节,减少了客户与子系统的耦合度。
封装使得用户更易于使用系统。
缺点:
外观类没有遵循开闭原则,当业务更替时需要直接修改外观类,比如需要在相片中使用GPS实时显示照相位置,则需要直接修改ICamera增加GPS定位功能的调用。
另一个用户相比之下,一定程度下增加外观类的接口数量,就像使用视频通话需要用到dailNumber();使用一般通话也需要dailNumber();一定程度上增加了用户使用成本。