您的位置:首页 > 科技 > 能源 > C# 设计模式之外观模式

C# 设计模式之外观模式

2024/9/24 3:27:47 来源:https://blog.csdn.net/qq_39847278/article/details/140918353  浏览:    关键词:C# 设计模式之外观模式

总目录


前言

在软件开发过程中,要完成一个功能,可能需要调用很多接口,不仅增加了代码间的耦合度,也增加了调试成本和维护的复杂度。不如我们把这些接口再封装一次,给一个很好的“外观”,让使用者使用更方便,只需调用一个接口,就可以完成以前调用多个接口的来完成任务,相信大家对这种编码技巧并不陌生,这就是本文将介绍的外观模式。


1 基础介绍

  1. 外观模式(Facade Pattern)也被称为 门面模式

  2. 来个图,直观的了解下
    在这里插入图片描述
    原本客户端需要直接调用多个不同子系统的接口,调用关系混乱,代码耦合度高,使用了外观模式后,所有的客户端只需和子系统的 门面 facade 打交道,子系统也只需和facade打交道,不仅捋顺了各个系统之间的关系,也减低了代码间的耦合度。

  3. 定义:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

  4. 使用外观模式时,我们创建了一个统一的类,用来包装子系统中一个或多个复杂的类,客户端可以直接通过外观类来调用内部子系统中方法,从而外观模式让客户和子系统之间避免了紧耦合。

  5. 外观模式包含如下两个角色:

    • 外观角色(Facade):在客户端可以调用它的方法,在外观角色中可以知道相关的(一个或者多个)子系统的功能和责任;在正常情况下,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理。

    • 子系统角色(SubSystem):在软件系统中可以有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能;每一个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观类传过来的请求;子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。

  6. 使用分析:

    • 一个系统可以有多个门面类
      在门面模式中,通常只需要一个门面类,并且此门面类只有一个实例,换言之它是一个单例类。当然这并不意味着在整个系统里只有一个门面类,而仅仅是说对每一个子系统只有一个门面类。或者说,如果一个系统有好几个子系统的话,每一个子系统都有一个门面类,整个系统可以有数个门面类。

    • 为子系统增加新行为
      初学者往往以为通过继承一个门面类便可在子系统中加入新的行为,这是错误的。门面模式的用意是为子系统提供一个集中化和简化的沟通管道,而不能向子系统加入新的行为。比如医院中的接待员并不是医护人员,接待员并不能为病人提供医疗服务。

    • Facade有助于建立层次结构的系统,实现了子系统与客户之间的松耦合关系,子系统内部的功能组件往往是紧耦合的。松耦合关系使得子系统的组件变化不会影响到它的客户。Facade消除了复杂的循环依赖关系。这一点在客户程序与子系统分别实现的时候格外重要。

    • 从客户程序的角度来看,Facade模式不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种程度上也达到了一种“解耦”的效果——内部子系统的任何变化不会影响到Facade接口的变化。

2 使用场景

  • 适用于一些有多个子系统,需要为这些复杂的系统提供一个统一接口的软件系统
  • 适用于存在多个子系统且需要保持子系统的独立性的时候
  • 在层次化结构中,可以使用外观模式定义系统中每一层的入口。其中三层架构就是这样的一个例子。

3 实现方式

以我们乘坐高铁为例,一般我们必须做以下步骤:

  • 购买高铁票
  • 过安检
  • 过检票口,进入高铁站,从站内乘坐高铁

1 当我们不使用外观模式的时候

    //车票子系统public class TicketsSys{//售票方法public void SaleTicket(){Console.WriteLine("售票系统 - 已售出高铁票一张");}}//安检系统public class SecurityCheckSys{//安检方法public void SecurityCheck(){Console.WriteLine("安检系统 - 已完成安检");}}//检票系统public class TicketCheckSys{public void TicketCheck(){Console.WriteLine("检票系统 - 已完成检票");}}

客户端调用各个子系统,实现乘坐高铁

        static void Main(string[] args){//1 先购买高铁票TicketsSys ticketsSys = new TicketsSys();ticketsSys.SaleTicket();//2 再进行安检SecurityCheckSys securityCheckSys = new SecurityCheckSys();securityCheckSys.SecurityCheck();//3 再检票TicketCheckSys ticketCheckSys = new TicketCheckSys();ticketCheckSys.TicketCheck();//4 最后 乘坐高铁Console.WriteLine("欢迎乘坐高铁,祝您旅途愉快!");Console.ReadKey();}

在上面的额案例中,客户端必须同时保存售票系统,安检系统,检票系统的引用,如果这些子系统发生改变时,此时客户端的调用代码也要随之改变,这样就没有很好的可扩展性。那我们看看外观模式是如何解决这个问题的。

2 使用外观模式时

	// 外观类 或 门面类//外观模式的核心类public class FacadeSys{private TicketsSys ticketsSys;private SecurityCheckSys securityCheckSys;private TicketCheckSys ticketCheckSys;public FacadeSys(){this.ticketsSys = new TicketsSys();this.securityCheckSys = new SecurityCheckSys();this.ticketCheckSys = new TicketCheckSys();}//乘坐高铁public void TakeHighspeedRail(){//1 先购买高铁票ticketsSys.SaleTicket();//2 再进行安检securityCheckSys.SecurityCheck();//3 再检票ticketCheckSys.TicketCheck();//4 最后 乘坐高铁Console.WriteLine("欢迎乘坐高铁,祝您旅途愉快!");}}//车票子系统public class TicketsSys{//售票方法public void SaleTicket(){Console.WriteLine("售票系统 - 已售出高铁票一张");}}//安检系统public class SecurityCheckSys{//安检方法public void SecurityCheck(){Console.WriteLine("安检系统 - 已完成安检");}}//检票系统public class TicketCheckSys{public void TicketCheck(){Console.WriteLine("检票系统 - 已完成检票");}}

客户端调用,实现乘坐高铁

        static void Main(string[] args){FacadeSys facadeSys = new FacadeSys();facadeSys.TakeHighspeedRail();Console.ReadKey();}

使用了外观模式之后,客户端只依赖与外观类,从而将客户端与子系统的依赖解耦了,如果子系统发生改变,此时客户端的代码并不需要去改变。外观模式的实现核心主要是:由外观类去保存各个子系统的引用,实现由一个统一的外观类去包装多个子系统类,然而客户端只需要引用这个外观类,然后由外观类来调用各个子系统中的方法。

外观模式的实现方式和适配器模式非常类似,然而外观模式与适配器模式不同的是:适配器模式是将一个对象包装起来以改变其接口,而外观是将一群对象 ”包装“起来以简化其接口。它们的意图是不一样的,适配器是将接口包装获得适配,而外观模式是提供一个统一的接口来简化接口。

4 优缺点分析

  • 优点

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

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

结语

希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:
C#设计模式之十外观模式(Facade Pattern)【结构型】
C#设计模式(11)——外观模式(Facade Pattern)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com