外观模式(Facade Pattern)

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/407 访问。

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

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

角色:

1、外观角色(Facade)

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

2、子系统角色(SubSystem)

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

示例:

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

namespace FacadePattern
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.TaxNo = {taxProof.TaxNo},");
Console.WriteLine($"TaxProof.Money = {taxProof.Money},");
Console.WriteLine($"TaxProof.PaymentData = {taxProof.PaymentData}!");
Console.WriteLine(Const.LINE_BREAK);
} }

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!
-------------------------------------------------------------

优点:

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/407 访问。

1、实现了子系统与客户端之间的松耦合关系;

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

缺点:

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

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

使用场景:

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

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

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

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

  1. Java设计模式之《外观模式》及应用场景

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6484128.html 1.外观模式简介 外观模式,一般用在子系统与访问之间,用于对访问屏蔽复 ...

  2. [设计模式] 10 外观模式 facade

    外观模式应该是用的很多的一种模式,特别是当一个系统很复杂时,系统提供给客户的是一个简单的对外接口,而把里面复杂的结构都封装了起来.客户只需使用这些简单接口就能使用这个系统,而不需要关注内部复杂的结构. ...

  3. C#设计模式学习笔记:(10)外观模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7772184.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲结构型设计模式的第五个模式--外 ...

  4. c#设计模式之:外观模式(Facade)

    一.引言 在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ...

  5. PHP设计模式之:外观模式

    外观模式: 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用: 外观模式又称为门面模 ...

  6. C#设计模式之十一外观模式(Facade)【结构型】

    一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...

  7. 设计模式学习心得<外观模式 Facade>

    外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 这种模式涉及 ...

  8. C#设计模式之十外观模式(Facade Pattern)【结构型】

    一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...

  9. 设计模式のFacadePattern(外观模式)----结构模式

    一.产生背景 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. ...

  10. Java设计模式学习记录-外观模式

    前言 这次要介绍的是外观模式(也称为门面模式),外观模式也属于结构型模式,其实外观模式还是非常好理解的,简单的来讲就是将多个复杂的业务封装成一个方法,在调用此方法时可以不必关系具体执行了哪些业务,而只 ...

随机推荐

  1. Ethical Hacking - Web Penetration Testing(6)

    REMOTE FILE INCLUSION Similar to local file inclusion. But allows an attacker to read ANY file from ...

  2. Linux find 查找 并删除文件 杀掉进程

    find 默认在当前 即 . 目录下查找 du 文件名 / 目录 # 查看文件占用内存大小 1. 按照文件名查找 find / -name qwe # qwe为文件名 find / -name *qw ...

  3. 集训作业 洛谷P1010 幂次方

    这个…… 这个题看上去有点难的样子. 仔细看看,感觉有点简单.啊,是递归啊,正经的看一看,好像是把一个数分成2的几次方的和. 然后余数和比他小的最大的2的次方数如果不是2的一次方或者2的0次方,就继续 ...

  4. JAVA I/O基本操作

    JAVA I/O基本操作 JAVA文件操作 JAVA字节流 JAVA字符流 JAVA缓存流 JAVA对象流 JAVA数据流 本文主要借鉴以下博客和网站: how2j.cn 深入理解java中的I/O ...

  5. Java集合框架1-- HashMap

    HashMap的知识点可以说在面试中经常被问到,是Java中比较常见的一种数据结构.所以这一篇就通过源码来深入理解下HashMap. 1 HashMap的底层是如何实现的?(基于JDK8) 1.1 H ...

  6. 痞子衡嵌入式:16MB以上NOR Flash使用不当可能会造成软复位后i.MXRT无法正常启动

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT上使用16MB以上NOR Flash软复位无法正常启动问题的分析解决经验. 痞子衡这几天在支持一个i.MXRT1050客户项 ...

  7. 人车识别实验丨华为ModelArts VS 百度Easy DL硬核体验

    摘要:想了解时下流行的自动驾驶相关AI模型吗?接下来就用华为云的ModelArts和百度的Easy DL带你体验一下AI平台是怎么进行模型训练的. 华为ModelArts自动学习 VS 百度Easy ...

  8. IO—》转换流和缓冲流

    转换流 摘要: InputStreamReader和OutputStreamWriter他们分别是FileReader和FileWriter的父类 当只是单纯的读写文件而不改变文件的编码格式时,就分别 ...

  9. layui常用插件(一) 轮播图

    轮播图 <html lang="en"> <head> <meta charset="UTF-8"> <meta ht ...

  10. 手牵手,从零学习Vue源码 系列一(前言-目录篇)

    系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 手牵手,从零学习Vue源码 系列三(虚拟DOM篇) 陆续更新中... 预计八月中旬更新 ...