在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ”门面“模式。下面就具体介绍下外观模式。

一、 外观(Facade)模式

外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。使用外观模式时,我们创建了一个统一的类,用来包装子系统中一个或多个复杂的类,客户端可以直接通过外观类来调用内部子系统中方法,从而外观模式让客户和子系统之间避免了紧耦合。

二、 外观模式的结构

然而对于外观模式而言,是没有一个一般化的类图描述,下面演示一个外观模式的示意性对象图来加深大家对外观模式的理解:

在上面的对象图中有两个角色:

  • 门面(Facade)角色:客户端调用这个角色的方法。该角色知道相关的一个或多个子系统的功能和责任,该角色会将从客户端发来的请求委派带相应的子系统中去。
  • 子系统(subsystem)角色:可以同时包含一个或多个子系统。每个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用或被门面角色调用。对于子系统而言,门面仅仅是另外一个客户端,子系统并不知道门面的存在。

三、 外观模式的实现

下面与学校中一个选课系统为例来解释外观模式,例如在选课系统中,有注册课程子系统和通知子系统,在不使用外观模式的情况下,客户端必须同时保存注册课程子系统和通知子系统两个引用,如果后期这两个子系统发生改变时,此时客户端的调用代码也要随之改变,这样就没有很好的可扩展性,下面看看不使用外观模式下选课系统的实现方式和客户端调用代码:

  1. using System;
  2.  
  3. /// <summary>
  4. /// 不使用外观模式的情况
  5. /// 此时客户端与三个子系统都发送了耦合,使得客户端程序依赖与子系统
  6. /// 为了解决这样的问题,我们可以使用外观模式来为所有子系统设计一个统一的接口
  7. /// 客户端只需要调用外观类中的方法就可以了,简化了客户端的操作
  8. /// 从而让客户和子系统之间避免了紧耦合
  9. /// </summary>
  10. class Client
  11. {
  12. static void Main(string[] args)
  13. {
  14. var a = new SubSystemA();
  15. var b = new SubSystemB();
  16. var c = new SubSystemC();
  17. a.MethodA();
  18. b.MethodB();
  19. c.MethodC();
  20. Console.Read();
  21. }
  22. }
  23.  
  24. // 子系统A
  25. public class SubSystemA
  26. {
  27. public void MethodA()
  28. {
  29. Console.WriteLine("执行子系统A中的方法A");
  30. }
  31. }
  32.  
  33. // 子系统B
  34. public class SubSystemB
  35. {
  36. public void MethodB()
  37. {
  38. Console.WriteLine("执行子系统B中的方法B");
  39. }
  40. }
  41.  
  42. // 子系统C
  43. public class SubSystemC
  44. {
  45. public void MethodC()
  46. {
  47. Console.WriteLine("执行子系统C中的方法C");
  48. }
  49. }

然而外观模式可以解决我们上面所说的问题,下面具体看看使用外观模式的实现:

  1. using System;
  2.  
  3. /// <summary>
  4. /// 以学生选课系统为例子演示外观模式的使用
  5. /// 学生选课模块包括功能有:
  6. /// 验证选课的人数是否已满
  7. /// 通知用户课程选择成功与否
  8. /// 客户端代码
  9. /// </summary>
  10. class Student
  11. {
  12. private static readonly RegistrationFacade Facade = new RegistrationFacade();
  13.  
  14. static void Main(string[] args)
  15. {
  16. Console.WriteLine(Facade.RegisterCourse("设计模式", "Learning Hard") ? "选课成功" : "选课失败");
  17.  
  18. Console.Read();
  19. }
  20. }
  21.  
  22. // 外观类
  23. public class RegistrationFacade
  24. {
  25. private readonly RegisterCourse _registerCourse;
  26. private readonly NotifyStudent _notifyStu;
  27. public RegistrationFacade()
  28. {
  29. _registerCourse = new RegisterCourse();
  30. _notifyStu = new NotifyStudent();
  31. }
  32.  
  33. public bool RegisterCourse(string courseName, string studentName)
  34. {
  35. return _registerCourse.CheckAvailable(courseName) && _notifyStu.Notify(studentName);
  36. }
  37. }
  38.  
  39. #region 子系统
  40. // 相当于子系统A
  41. public class RegisterCourse
  42. {
  43. public bool CheckAvailable(string courseName)
  44. {
  45. Console.WriteLine("正在验证课程 {0}是否人数已满", courseName);
  46. return true;
  47. }
  48. }
  49.  
  50. // 相当于子系统B
  51. public class NotifyStudent
  52. {
  53. public bool Notify(string studentName)
  54. {
  55. Console.WriteLine("正在向{0}发生通知", studentName);
  56. return true;
  57. }
  58. }
  59. #endregion

使用了外观模式之后,客户端只依赖与外观类,从而将客户端与子系统的依赖解耦了,如果子系统发生改变,此时客户端的代码并不需要去改变。外观模式的实现核心主要是——由外观类去保存各个子系统的引用,实现由一个统一的外观类去包装多个子系统类,然而客户端只需要引用这个外观类,然后由外观类来调用各个子系统中的方法。然而这样的实现方式非常类似适配器模式,然而外观模式与适配器模式不同的是:适配器模式是将一个对象包装起来以改变其接口,而外观是将一群对象 ”包装“起来以简化其接口。它们的意图是不一样的,适配器是将接口转换为不同接口,而外观模式是提供一个统一的接口来简化接口。

四、 使用场景

在以下情况下可以考虑使用外观模式:

  • 外一个复杂的子系统提供一个简单的接口
  • 提供子系统的独立性
  • 在层次化结构中,可以使用外观模式定义系统中每一层的入口。其中三层架构就是这样的一个例子

五、 外观模式的优缺点

优点:

  1. 外观模式对客户屏蔽了子系统组件,从而简化了接口,减少了客户处理的对象数目并使子系统的使用更加简单。
  2. 外观模式实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件是紧耦合的。松耦合使得子系统的组件变化不会影响到它的客户。

缺点:

  1. 如果增加新的子系统可能需要修改外观类或客户端的源代码,这样就违背了”开——闭原则“(不过这点也是不可避免)。

六、 总结

到这里外观模式的介绍就结束了,外观模式,为子系统的一组接口提供一个统一的接口,该模式定义了一个高层接口,这一个高层接口使的子系统更加容易使用。并且外观模式可以解决层结构分离、降低系统耦合度和为新旧系统交互提供接口功能

C#设计模式-外观模式的更多相关文章

  1. java设计模式——外观模式(门面模式)

    一. 定义与类型 定义:门面模式,提供一个统一的接口,用来访问子系统中的一群接口,门面模式定义了一个高层接口,让子系统更容易使用 类型:结构性 二. 使用场景 子系统越来越复杂,增加外观模式提供简单调 ...

  2. Java设计模式——外观模式

    JAVA 设计模式 外观模式 用途 外观模式 (Facade) 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式是一种结构型模式. 结构

  3. 浅谈Python设计模式 - 外观模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 外观模式 外观模式的核心在于将复杂的内部实现包装起来,只向外界提供简单的调用接口 ...

  4. 【设计模式】Java设计模式 - 外观模式

    Java设计模式 - 外观模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  5. [Head First设计模式]生活中学设计模式——外观模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  6. JAVA 设计模式 外观模式

    用途 外观模式 (Facade) 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式是一种结构型模式. 结构

  7. Java设计模式---外观模式

    外观模式(Facade) 外观模式的意图是:为子系统提供一个接口,便于它的使用.   解释: 简单的说,外观模式就是封装多个上层应用需要的方法,使得上层调用变得简单,为上层提供简单的接口,是设计模式中 ...

  8. 设计模式——外观模式(Facade)

    1. 概述     外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性. 例子1:一个电源总开关可以控制四盏灯 ...

  9. 设计模式 | 外观模式/门面模式(facade)

    定义: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 结构:(书中图,侵删) 一个简洁易用的外观类 一个复杂的子系统   实例: 书中提到了理 ...

随机推荐

  1. 浩瀚技术团队... 安卓智能POS移动PDA开单器 开单器 进销存系统 进销存系统

    浩瀚技术团队... 智能POS移动PDA开单器 开单器 进销存系统 进销存系统 点餐 会员管理 会员管理 深度解读 手机APP移动办公到底是什么? 快速打单POS·不仅仅是快那么简单!  

  2. ViewPager+Fragment取消预加载(延迟加载)(转)

    原文:http://www.2cto.com/kf/201501/368954.html 在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragmen ...

  3. CustomUI Direct3D9_Sample

    刚开始建这个项目的时候编译器报了很多Link2019的错误. 后来添加了一些lib文件才解决,参考    缺少.lib文件导致的Link2019 解决方案汇总 ==================== ...

  4. CentOS 6.4下编译安装MySQL 5.6.14

    概述: CentOS 6.4下通过yum安装的MySQL是5.1版的,比较老,所以就想通过源代码安装高版本的5.6.14. 正文: 一:卸载旧版本 使用下面的命令检查是否安装有MySQL Server ...

  5. [杂谈]冲NOIP一等奖。。

    唉不想多说了. 真是一段“传奇”的经历啊. 还是那句话..“是的我上次什么都没说就走了...”这次也一样. 我还是太单纯的以为我们是肯定能够参加北大的夏令营的..然而结果真是意料之外啊. 本来我以为我 ...

  6. Oracle Flashback 闪回

    Oracle 的闪回技术是一种数据恢复技术,仅能对用户逻辑错误进行恢复, 闪回针对的是提交commit的事务,没有提交的事务,使用rollback 1.闪回版本查询 Flashback Version ...

  7. Hive文件存储格式

    hive文件存储格式 1.textfile textfile为默认格式   存储方式:行存储   磁盘开销大 数据解析开销大   压缩的text文件 hive无法进行合并和拆分 2.sequencef ...

  8. APP设计资源

    在开发独立客户端时,需要一些不同尺寸的图标和图片,统计如下. APP 图标 ICON iOS:(主要需要这三类图标) 58x58 87x87 (Spotlight & Settings) 80 ...

  9. DSY2287*消失之物

    Description ftiasch 有 N 个物品, 体积分别是 W1, W2, ..., WN. 由于她的疏忽, 第 i 个物品丢失了. "要使用剩下的 N - 1 物品装满容积为 x ...

  10. 启动项目的时候报驱动错误: not support oracle driver 1.0

    问题:今天在使用pom导入oracle14的包时候发现怎么都下载不过来.网上查了一下发现是因为Oracle驱动需要官方授权,所以在pom.xml文件直接配置,无法下载成功. 解决方法就是下载oracl ...