• 外观模式:也叫门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
  • 它向现有的系统添加一个接口,用这一个接口来隐藏实际的系统的复杂性。
  • 使用外观模式,他外部看起来就是一个接口,其实他的内部有很多复杂的接口已经被实现

使用场景:

  • 为复杂的模块或子系统提供外界访问的模块
  • 子系统相对独立
  • 预防低水平人员带来的风险

    示例

    描述
    生活中使用外观模式的栗子非常多,任何一个类似中央调度结构的组织都是一种外观模式的应用。比如手机,它集电话、短信、拍照等功能于一身,只需通过点击手机屏幕 (外观) 就可以使用,并不需要了解具体功能的内部细节 (系统复杂性)。
    画图
    外观模式 - 图1
    写代码
    手机系统模拟代码: ```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); }

  1. @Override
  2. public void hangup() {
  3. System.out.println("挂断电话");
  4. }

}

  1. ```java
  2. // 抽象出相机功能接口 (如打开相机、关闭相机)
  3. public interface ICamera {
  4. void open();
  5. void close();
  6. }
  7. // 实现相机功能接口的具体类
  8. public class DefaultCameraImpl implements ICamera {
  9. @Override
  10. public void open() {
  11. System.out.println("打开相机");
  12. }
  13. @Override
  14. public void close() {
  15. System.out.println("关闭相机");
  16. }
  17. }
  1. // 手机 (集成了电话和相机功能,并提供了相关的方法)
  2. public class MobilePhone {
  3. private IPhone mDefaultPhone;
  4. private ICamera mDefaultCamera;
  5. public MobilePhone() {
  6. mDefaultPhone = new DefaultPhoneImpl();
  7. mDefaultCamera = new DefaultCameraImpl();
  8. }
  9. public void callSomeone(String phoneNumber) {
  10. mDefaultPhone.call(phoneNumber);
  11. }
  12. public void hangup() {
  13. mDefaultPhone.hangup();
  14. }
  15. public void takePicture() {
  16. mDefaultCamera.open();
  17. System.out.println("拍照");
  18. mDefaultCamera.close();
  19. }
  20. public void startVideoChat() {
  21. mDefaultCamera.open();
  22. System.out.println("开始视频聊天");
  23. mDefaultCamera.close();
  24. }
  25. }

模拟手机系统的代码到这里就差不多了,接下来是测试代码:

  1. public static void main(String[] args) {
  2. MobilePhone mobilePhone = new MobilePhone();
  3. mobilePhone.callSomeone("123456");
  4. mobilePhone.hangup();
  5. mobilePhone.takePicture();
  6. mobilePhone.startVideoChat();
  7. }

日志输出如下:

  1. 拨打电话:123456
  2. 挂断电话
  3. 打开相机
  4. 拍照
  5. 关闭相机
  6. 打开相机
  7. 开始视频聊天
  8. 关闭相机

MobilePhone 类可以理解为手机的外观,DefaultPhoneImplDefaultCameraImpl 可以理解为手机内部的复杂细节。我们通过 MobilePhone 使用电话或相机功能的时候,只使用其暴露出来的方法就好了,并不需要了解其内部的细节。

扩展

使用者既然不需要了解外观模式隐藏了的复杂细节,那么日后我们在调整这些细节时也就不会对使用者造成影响了。比如说,系统自带相机拍出来的人像照并不好看,我们想改为使用第三方相机进行拍照,如「美颜相机」:
代码改写后如下:

  1. // 增加美图相机实现类
  2. public class MeituCameraImpl implements ICamera {
  3. @Override
  4. public void open() {
  5. System.out.println("打开美图相机");
  6. }
  7. @Override
  8. public void close() {
  9. System.out.println("关闭美图相机");
  10. }
  11. }
  12. // 增加 mMeituCamera 实例变量
  13. public class MobilePhone {
  14. private IPhone mDefaultPhone;
  15. private ICamera mDefaultCamera;
  16. private ICamera mMeituCamera;
  17. public MobilePhone() {
  18. mDefaultPhone = new DefaultPhoneImpl();
  19. mDefaultCamera = new DefaultCameraImpl();
  20. mMeituCamera = new MeituCameraImpl();
  21. }
  22. public void takePicture() {
  23. // 打开和关闭的都改为美图相机
  24. mMeituCamera.open();
  25. System.out.println("拍照");
  26. mMeituCamera.close();
  27. }
  28. // ...
  29. }

此时,日志输出是:

  1. 打开美图相机
  2. 拍照
  3. 关闭关闭相机

总结

在这篇文章中,我们演示了外观模式的使用,它的:

  • 意图:通过抽象出一组接口或方法,简化了使用者的操作逻辑。
  • 优点:减少系统间的相互依赖,提高灵活性和安全性。
  • 缺点:要改东西的话有点麻烦,继承和重写都不合适。