- 外观模式:也叫门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
- 它向现有的系统添加一个接口,用这一个接口来隐藏实际的系统的复杂性。
- 使用外观模式,他外部看起来就是一个接口,其实他的内部有很多复杂的接口已经被实现
使用场景:
- 为复杂的模块或子系统提供外界访问的模块
- 子系统相对独立
- 预防低水平人员带来的风险
示例
描述
生活中使用外观模式的栗子非常多,任何一个类似中央调度结构的组织都是一种外观模式的应用。比如手机,它集电话、短信、拍照等功能于一身,只需通过点击手机屏幕 (外观) 就可以使用,并不需要了解具体功能的内部细节 (系统复杂性)。
画图
写代码
手机系统模拟代码: ```java // 抽象出电话功能接口 (如拨打电话、挂断电话) public interface IPhone { void call(String phoneNumber); void hangup(); }
// 实现电话功能接口的具体类 public class DefaultPhoneImpl implements IPhone { @Override public void call(String phoneNumber) { System.out.println(“拨打电话:” + phoneNumber); }
@Overridepublic void hangup() {System.out.println("挂断电话");}
}
```java// 抽象出相机功能接口 (如打开相机、关闭相机)public interface ICamera {void open();void close();}// 实现相机功能接口的具体类public class DefaultCameraImpl implements ICamera {@Overridepublic void open() {System.out.println("打开相机");}@Overridepublic void close() {System.out.println("关闭相机");}}
// 手机 (集成了电话和相机功能,并提供了相关的方法)public class MobilePhone {private IPhone mDefaultPhone;private ICamera mDefaultCamera;public MobilePhone() {mDefaultPhone = new DefaultPhoneImpl();mDefaultCamera = new DefaultCameraImpl();}public void callSomeone(String phoneNumber) {mDefaultPhone.call(phoneNumber);}public void hangup() {mDefaultPhone.hangup();}public void takePicture() {mDefaultCamera.open();System.out.println("拍照");mDefaultCamera.close();}public void startVideoChat() {mDefaultCamera.open();System.out.println("开始视频聊天");mDefaultCamera.close();}}
模拟手机系统的代码到这里就差不多了,接下来是测试代码:
public static void main(String[] args) {MobilePhone mobilePhone = new MobilePhone();mobilePhone.callSomeone("123456");mobilePhone.hangup();mobilePhone.takePicture();mobilePhone.startVideoChat();}
日志输出如下:
拨打电话:123456挂断电话打开相机拍照关闭相机打开相机开始视频聊天关闭相机
MobilePhone 类可以理解为手机的外观,DefaultPhoneImpl 和 DefaultCameraImpl 可以理解为手机内部的复杂细节。我们通过 MobilePhone 使用电话或相机功能的时候,只使用其暴露出来的方法就好了,并不需要了解其内部的细节。
扩展
使用者既然不需要了解外观模式隐藏了的复杂细节,那么日后我们在调整这些细节时也就不会对使用者造成影响了。比如说,系统自带相机拍出来的人像照并不好看,我们想改为使用第三方相机进行拍照,如「美颜相机」:
代码改写后如下:
// 增加美图相机实现类public class MeituCameraImpl implements ICamera {@Overridepublic void open() {System.out.println("打开美图相机");}@Overridepublic void close() {System.out.println("关闭美图相机");}}// 增加 mMeituCamera 实例变量public class MobilePhone {private IPhone mDefaultPhone;private ICamera mDefaultCamera;private ICamera mMeituCamera;public MobilePhone() {mDefaultPhone = new DefaultPhoneImpl();mDefaultCamera = new DefaultCameraImpl();mMeituCamera = new MeituCameraImpl();}public void takePicture() {// 打开和关闭的都改为美图相机mMeituCamera.open();System.out.println("拍照");mMeituCamera.close();}// ...}
此时,日志输出是:
打开美图相机拍照关闭关闭相机
总结
在这篇文章中,我们演示了外观模式的使用,它的:
- 意图:通过抽象出一组接口或方法,简化了使用者的操作逻辑。
- 优点:减少系统间的相互依赖,提高灵活性和安全性。
- 缺点:要改东西的话有点麻烦,继承和重写都不合适。
