【愚公系列】2023年10月 二十三种设计模式(十)-外观模式(Facade Pattern)

举报
愚公搬代码 发表于 2021/12/04 18:45:27 2021/12/04
【摘要】 设计模式(Design Pattern)是软件开发领域的宝贵经验,是多人反复借鉴和广泛应用的代码设计指导。它们是一系列经过分类和归纳的代码组织方法,旨在实现可重用性、可维护性和可理解性。使用设计模式,我们能够编写高质量的代码,使其更易于他人理解,并提供了代码可靠性的保证。

🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀前言

设计模式(Design Pattern)是软件开发领域的宝贵经验,是多人反复借鉴和广泛应用的代码设计指导。它们是一系列经过分类和归纳的代码组织方法,旨在实现可重用性、可维护性和可理解性。使用设计模式,我们能够编写高质量的代码,使其更易于他人理解,并提供了代码可靠性的保证。

毫无疑问,设计模式对个人、团队和整个系统都带来了显著的益处。它们将代码开发提升到工程化水平,为软件工程构建提供了坚实的基础,就如同大厦的一块块精巧的砖石一样。在项目中明智地应用设计模式可以完美地解决各种复杂问题。每种设计模式都有相应的原理和最佳实践,它们描述了我们日常开发中不断遇到的问题,以及这些问题的核心解决方法。正是因为这种实用性和通用性,设计模式才能在软件开发中广泛地得以应用。设计模式是构建稳健、可扩展和可维护软件的关键工具,为开发者们提供了解决问题的智慧和指导。

🚀一、外观模式(Facade Pattern)

外观模式属于结构型设计模式,其主要目的是隐藏系统内部的复杂性,为客户端提供一个简化的接口,使客户端能够更容易地访问系统。

外观模式提供了一个统一的接口,该接口整合了子系统中一组接口,使子系统更易于访问和使用。这种模式使客户端不必了解子系统的详细实现,而只需与外观接口交互,从而降低了客户端与系统之间的耦合度。外观模式通常用于简化复杂系统的操作,提高代码的可维护性和可读性。

🚀二、使用步骤

🔎1.角色

🦋1.1 外观角色(Facade)

外观模式(Facade Pattern)中的外观角色(Facade)是该模式的关键组成部分,具有重要的概念和作用:

  1. 概念:外观角色是外观模式的核心,它是一个接口或类,用于向客户端提供简化的接口,以访问系统中的一组相关子系统或一系列复杂的类。外观角色的目标是隐藏系统内部的复杂性,使客户端不需要了解系统的具体细节。

  2. 作用

    • 简化接口:外观角色的主要作用是简化系统的接口,为客户端提供一个更高层次的接口,客户端可以通过这个接口来访问系统的功能,而无需了解每个子系统的详细操作方式。
    • 隐藏实现细节:外观角色将系统的实现细节封装起来,将复杂性从客户端移动到了外观角色本身,使客户端能够专注于业务逻辑而不必担心系统的复杂性。
    • 降低耦合度:外观角色降低了客户端与系统之间的耦合度。客户端只需与外观角色交互,不需要与多个子系统直接交互,从而降低了依赖性。
    • 提高可维护性:通过使用外观模式,系统的维护变得更加容易,因为任何系统内部的变化只需要在外观角色中进行处理,而不会影响客户端。

外观角色的存在使得客户端的代码更加简洁和易读,同时提供了一种有效的方式来管理复杂系统的复杂性。这在大型软件项目中特别有用,可以帮助团队更好地组织和维护代码。

🦋1.2 子系统角色(SubSystem)

外观模式(Facade Pattern)中的子系统角色(SubSystem)是指组成整个系统的各个组件、类或模块。这些子系统角色是外观模式的一部分,具有以下概念和作用:

  1. 概念:子系统角色是系统内部的各个组成部分,它们负责执行系统的具体功能和任务。这些组件通常是高度内聚的,用于完成特定的工作,但客户端通常不需要直接与它们交互。

  2. 作用

    • 实现具体功能:子系统角色的主要作用是实现系统的各种具体功能。每个子系统角色通常负责一部分功能,例如数据库访问、日志记录、用户认证等。
    • 提供服务:子系统角色为外观角色(Facade)提供服务。外观角色通过调用子系统角色的方法来执行复杂的操作,从而隐藏了系统内部的复杂性。
    • 解耦客户端和子系统:外观模式的核心目标之一是解耦客户端和系统内部的子系统。客户端不需要了解系统内部的每个子系统的细节,而是通过外观接口与系统交互。
    • 提高可维护性:将系统的功能模块化并封装在子系统角色中有助于提高系统的可维护性。每个子系统可以独立开发、测试和维护,而不会干扰其他部分。

子系统角色在外观模式中扮演着实际执行系统功能的角色,它们的存在有助于将系统内部的复杂性隐藏起来,同时提供了一个简化的接口供外观角色和客户端使用。这种模式有助于提高系统的可维护性、可扩展性和可理解性,特别是在大型软件项目中。

🔎2.示例

在这里插入图片描述

命名空间FacadePattern中包含外观类Facade,提供公开的Handle方法,Haikwan是海关类,可以通过Apply方法从后台取得一个加密的完税凭证JSON数据,Decrypt类为解密类,可以解密海关的JSON数据,TaxProof则是完税凭证类,可以将JSON反序列化成一个对象,FileStore则将完税凭证数据持久化到文件中。本案例尝试通过一个从海关获取数据、解密、反序列化、保存到文件的完整流程来向大家简明扼要的阐述外观模式的使用。

public class Haikwan {
 
    public string Apply(Uri uri) {
        Console.WriteLine($"Apply some data from {uri.ToString()}!");
        return Const.TEMPLET_HAIKWAN;
    }
 
}

海关类Haikwan,包含一个Apply方法可以从海关的后台获取一个加密的JSON数据。

public class Decrypt {

    public string Decipher(string ciphertext) {
        Console.WriteLine("Deciphering ciphertext!");
        Console.WriteLine(Const.LINE_BREAK);
        Console.WriteLine(ciphertext);
        Console.WriteLine(Const.LINE_BREAK);
        return ciphertext;
    }

}

解密类Decrypt,将加密的JSON数据用Decipher方法解密成原始JSON数据。

public class TaxProof {

    public string TaxNo { get; private set; }

    public decimal Money { get; private set; }

    public DateTime PaymentData { get; private set; }

    public void Deserialize(string plaintext) {
        Console.WriteLine("Creating TaxProof Instance from plaintext!");
        TaxNo = "287361039374492-A01";
        Money = 1986.1020m;
        PaymentData = new DateTime(2018, 07, 20);
    }

}

TaxProof完税凭证类,将JSON数据反序列化成实体对象,以便使用类的面向对象语言的优势进行后续的处理。

本例中没有真正实现反序列化的动作,仅仅作为一个演示使用了Hard Code。在实际开发过程中,推荐使用Newtonsoft.Json来处理序列化和反序列化。

public class FileStore
    {
        public void Store(TaxProof taxProof)
        {
            Console.WriteLine("Saving taxProof instance to file!");
            Console.WriteLine($"TaxProof.TasNo={taxProof.TasNo},");
            Console.WriteLine($"TaxProof.TasNo={taxProof.TasNo},");
            Console.WriteLine($"TaxProof.TasNo={taxProof.TasNo},");
            Console.WriteLine($"TaxProof.TasNo={taxProof.TasNo},");
        }
    }

FileStore文件保存类,将完税凭证数据持久化到文件中。

public class Facade {

    private Haikwan _haikwan = null;
    private Decrypt _decrypt = null;
    private TaxProof _taxProof = null;
    private FileStore _fileStore = null;

    public Facade() {
        _haikwan = new Haikwan();
        _decrypt = new Decrypt();
        _taxProof = new TaxProof();
        _fileStore = new FileStore();
    }

    public void Handle(Uri uri) {
        var ciphertext = _haikwan.Apply(uri);
        var plaintext = _decrypt.Decipher(ciphertext);
        _taxProof.Deserialize(plaintext);
        _fileStore.Store(_taxProof);
    }

}

Facade外观类,这是外观模式的核心类,首先在内部维持对海关类Haikwan、解密类Decrypt、完税凭证类TaxProof、文件保存类FileStore的引用,并在构造函数中创建它们,公开的Handle方法处理一个完整的从海关获取数据到持久化文件的完整流程。

public class Const {

    public const string TEMPLET_HAIKWAN = "{\r\n" +
        "  \"Haikwan\": {\r\n" +
        "    \"TaxNo\": \"287361039374492-A01\",\r\n" +
        "    \"Money\": 1986.1020,\r\n" +
        "    \"PaymentData\": \"\\/Date(1532099596)\\/\"\r\n" +
        "  }\r\n" +
        "}";

    public const string LINE_BREAK =
        "-------------------------------------------------------------";

    public const string HAIKWAN_URI =
        "http://@copyright#www.customs.gov.cn";

}

Const常量类,统一管理本案例中用到的字符串资源。实际开发过程中不应当出现此类,请参考2017年阿里发布的《阿里巴巴Java开发手册》,此规则对C#开发者来说也应当遵守。

public class Program {

    private static Facade _facade = null;

    public static void Main(string[] args) {
        _facade = new Facade();
        _facade.Handle(new Uri(Const.HAIKWAN_URI));

        Console.ReadKey();
    }

}

调用方的代码,仅仅需要一行代码就完成了一个完整的流程。以下是这个案例的输出结果:

Apply some data from http://@copyright/#www.customs.gov.cn!
Deciphering ciphertext!
-------------------------------------------------------------
{
  "Haikwan": {
    "TaxNo": "287361039374492-A01",
    "Money": 1986.1020,
    "PaymentData": "\/Date(1532099596)\/"
  }
}
-------------------------------------------------------------
Creating TaxProof Instance from plaintext!
Saving taxProof instance to file!
TaxProof.TaxNo = 287361039374492-A01,
TaxProof.Money = 1986.1020,
TaxProof.PaymentData = 2018-07-20 00:00:00!
-------------------------------------------------------------

🚀总结

🔎1.优点

外观模式(Facade Pattern)有许多优点,这些优点使它成为一种有用的设计模式,特别适用于管理复杂系统。以下是外观模式的一些主要优点:

  1. 简化客户端代码:外观模式通过提供一个统一的简化接口,将复杂系统的操作和功能隐藏在背后,使客户端代码变得更加简单和易于理解。客户端不需要了解系统的内部结构和细节。

  2. 降低耦合度:外观模式有助于降低客户端与系统内部子系统之间的耦合度。客户端只与外观角色交互,而不需要直接与多个子系统交互,这减少了依赖性,使系统更加灵活和可维护。

  3. 隐藏复杂性:外观模式隐藏了系统内部的复杂性和实现细节。这使得系统更容易理解和维护,因为复杂性被封装在外观角色和子系统中。

  4. 提高可维护性:将功能模块化并封装在子系统中有助于提高系统的可维护性。每个子系统可以独立开发、测试和维护,降低了系统维护的难度。

  5. 促进系统扩展:外观模式使系统更容易扩展。可以通过修改外观角色或添加新的子系统来扩展系统的功能,而不必修改客户端代码。

  6. 提高安全性:通过外观模式,可以将某些功能模块的访问权限限制在外观角色之下,从而提高系统的安全性。客户端只能通过外观角色来访问这些功能,不直接暴露给客户端。

  7. 改善代码组织:外观模式有助于改善代码组织结构,使系统更易于管理和理解。不同的功能模块被封装在不同的子系统中,提高了代码的可读性和可维护性。

外观模式是一种有效的设计模式,用于简化复杂系统的操作和管理,提高代码的可维护性和可读性,降低了系统的耦合度,使系统更加灵活和易于扩展。

🔎2.缺点

外观模式(Facade Pattern)虽然有许多优点,但也有一些缺点和限制,需要考虑和权衡:

  1. 增加了一个额外的抽象层:引入外观角色会增加一个额外的抽象层,有时可能会导致性能略微下降。对于一些对性能要求极高的应用,这个额外开销可能是不可接受的。

  2. 不适合所有情况:外观模式并不是适用于所有情况的通用解决方案。在某些情况下,直接与系统的各个子系统交互可能更加灵活和高效。

  3. 可能导致外观角色变得臃肿:如果系统变得非常复杂,外观角色可能会变得庞大和复杂,难以维护。这可能违反了单一职责原则,导致外观角色负责太多不同的功能。

  4. 限制了灵活性:外观模式的目的是简化接口,这可能会限制客户端访问系统的某些高级功能。如果客户端需要更多的控制权和灵活性,外观模式可能不适合。

  5. 不处理所有系统功能:外观模式通常只会暴露系统的一部分功能,这意味着某些功能可能仍然需要通过直接访问子系统来实现,这可能导致一致性问题。

外观模式是一种有用的设计模式,但在使用时需要权衡其优点和缺点,确保它适合特定的应用场景。它最适合于需要简化复杂系统接口、降低耦合度和提高可维护性的情

🔎3.使用场景

外观模式(Facade Pattern)在以下情况下特别有用,适合被应用:

  1. 简化复杂系统:当系统变得复杂,包含多个子系统,而客户端只需要与系统的一部分或某些功能交互时,外观模式可以提供一个简化的接口,隐藏系统的复杂性。

  2. 降低耦合度:当需要降低客户端与系统内部子系统之间的耦合度时,外观模式是一个有效的方式。它通过引入外观角色,减少了客户端与子系统之间的直接依赖关系。

  3. 提供统一接口:当需要为多个不同的客户端提供相同或类似的接口时,外观模式可以提供一个统一的接口,以便客户端更容易理解和使用系统。

  4. 模块化系统:外观模式有助于将系统功能模块化,每个子系统独立开发和维护。这使得系统更易于管理,特别是在大型软件项目中。

  5. 改善安全性:通过外观模式,可以将某些敏感功能模块的访问权限限制在外观角色之下,提高系统的安全性。

  6. 支持系统扩展:如果需要在不修改客户端代码的情况下扩展系统功能,外观模式可以允许添加新的子系统或修改外观角色来实现扩展。

  7. 提高可读性和可维护性:外观模式有助于改善代码的可读性和可维护性,因为它将系统的复杂性封装在一个统一的外观接口之后,使代码更加清晰。

外观模式适用于需要简化、组织和管理复杂系统的情况,以及需要降低客户端与系统内部组件之间耦合度的情况。它有助于提高代码的可维护性、可读性和可扩展性,使系统更容易理解和维护。


🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

在这里插入图片描述

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。