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

简介: 【愚公系列】2021年12月 二十三种设计模式(十)-外观模式(Facade Pattern)

文章目录

前言

一、外观模式(Facade Pattern)

二、使用步骤

角色

示例

总结

优点

缺点

使用场景

前言

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。


提示:以下是本篇文章正文内容,下面案例可供参考


一、外观模式(Facade Pattern)

外观模式属于结构型模式,它隐藏了系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。


为子系统中的一组接口提供了一个统一的访问接口,这个接口使得子系统更容易被访问或者使用。


二、使用步骤

角色

1、外观角色(Facade)


外观模式的核心,它被客户角色调用,它熟悉子系统的各项功能,可以在内部根据需求预定几种功能的组合;


2、子系统角色(SubSystem)


实现了子系统的功能,它内部可以有系统内的相互交互,也可以由供外界调用的接口。


示例

image.png

命名空间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、实现了子系统与客户端之间的松耦合关系;

2、客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易。


缺点

1、不符合开闭原则,如果要修改某一个子系统的功能,通常外观类也要一起修改;

2、没有办法直接阻止外部不通过外观类访问子系统的功能,因为子系统类中的功能必须是公开的(根据需要决定是否使用internal访问级别可解决这个缺点,但外观类需要和子系统类在同一个程序集内)。


使用场景

1、设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观模式;

2、开发阶段,子系统越来越复杂,增加外观模式提供一个简单的调用接口;

3、维护一个大型遗留系统的时候,可能这个系统已经非常难以维护和扩展,但又包含非常重要的功能,为其开发一个外观类,以便新系统与其交互。


相关文章
|
3月前
|
设计模式
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
这篇文章详细解释了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。每种模式都通过代码示例展示了其应用场景和实现方法,并比较了它们之间的差异。简单工厂模式通过一个工厂类来创建各种产品;工厂方法模式通过定义一个创建对象的接口,由子类决定实例化哪个类;抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不需要明确指定具体类。
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
|
3月前
|
设计模式 Java
Java设计模式-外观模式(11)
Java设计模式-外观模式(11)
|
2月前
|
设计模式 Java
Java设计模式之外观模式
这篇文章详细解释了Java设计模式之外观模式的原理及其应用场景,并通过具体代码示例展示了如何通过外观模式简化子系统的使用。
32 0
|
4月前
|
设计模式 存储 Java
【九】设计模式~~~结构型模式~~~外观模式(Java)
文章详细介绍了外观模式(Facade Pattern),这是一种对象结构型模式,通过引入一个外观类来简化客户端与多个子系统之间的交互,降低系统的耦合度,并提供一个统一的高层接口来使用子系统。通过文件加密模块的实例,展示了外观模式的动机、定义、结构、优点、缺点以及适用场景,并讨论了如何通过引入抽象外观类来提高系统的可扩展性。
【九】设计模式~~~结构型模式~~~外观模式(Java)
|
3月前
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
5月前
|
设计模式 JavaScript 前端开发
js设计模式【详解】—— 外观模式
js设计模式【详解】—— 外观模式
42 2
|
6月前
|
设计模式
设计模式-05建造者模式(Builder Pattern)
设计模式-05建造者模式(Builder Pattern)
|
6月前
|
设计模式 Java
Java设计模式:外观模式之优雅门面(九)
Java设计模式:外观模式之优雅门面(九)
|
6月前
|
设计模式 Java
Java设计模式之外观模式详解
Java设计模式之外观模式详解
|
7月前
|
设计模式 安全 Java
【设计模式】JAVA Design Patterns——Curiously Recurring Template Pattern(奇异递归模板模式)
该文介绍了一种C++的编程技巧——奇异递归模板模式(CRTP),旨在让派生组件能继承基本组件的特定功能。通过示例展示了如何创建一个`Fighter`接口和`MmaFighter`类,其中`MmaFighter`及其子类如`MmaBantamweightFighter`和`MmaHeavyweightFighter`强制类型安全,确保相同重量级的拳手之间才能进行比赛。这种设计避免了不同重量级拳手间的错误匹配,编译时会报错。CRTP适用于处理类型冲突、参数化类方法和限制方法只对相同类型实例生效的情况。
【设计模式】JAVA Design Patterns——Curiously Recurring Template Pattern(奇异递归模板模式)