C#设计模式之10-外观模式
外观模式(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-外观模式的更多相关文章
- Java设计模式之《外观模式》及应用场景
原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6484128.html 1.外观模式简介 外观模式,一般用在子系统与访问之间,用于对访问屏蔽复 ...
- [设计模式] 10 外观模式 facade
外观模式应该是用的很多的一种模式,特别是当一个系统很复杂时,系统提供给客户的是一个简单的对外接口,而把里面复杂的结构都封装了起来.客户只需使用这些简单接口就能使用这个系统,而不需要关注内部复杂的结构. ...
- C#设计模式学习笔记:(10)外观模式
本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7772184.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲结构型设计模式的第五个模式--外 ...
- c#设计模式之:外观模式(Facade)
一.引言 在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ...
- PHP设计模式之:外观模式
外观模式: 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用: 外观模式又称为门面模 ...
- C#设计模式之十一外观模式(Facade)【结构型】
一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...
- 设计模式学习心得<外观模式 Facade>
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 这种模式涉及 ...
- C#设计模式之十外观模式(Facade Pattern)【结构型】
一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...
- 设计模式のFacadePattern(外观模式)----结构模式
一.产生背景 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. ...
- Java设计模式学习记录-外观模式
前言 这次要介绍的是外观模式(也称为门面模式),外观模式也属于结构型模式,其实外观模式还是非常好理解的,简单的来讲就是将多个复杂的业务封装成一个方法,在调用此方法时可以不必关系具体执行了哪些业务,而只 ...
随机推荐
- vpp之clib.h分析
vpp代码中有一个clib.h,其中封装了很一些很经典的位运算: //计算以2为底的对数,log2(x) //也就是计算2的N次方为x.x为uint32类型 #if defined (count_le ...
- Python Ethical Hacking - MAC Address & How to Change(1)
MAC ADDRESS Media Access Control Permanent Physical Unique Assigned by manufacturer WHY CHANGE THE M ...
- OSCP Learning Notes - File Transfers(2)
Metasploit Target Server: Kioptrix Level 1 (1) Start the Metasploit on Kali Linux. (2) Set the modul ...
- three.js 将图片马赛克化
这篇郭先生来说说BufferGeometry,类型化数组和粒子系统的使用,并且让图片有马赛克效果(同理可以让不清晰的图片清晰化),如图所示.在线案例点击博客原文 1. 解析图片 解析图片和上一篇一样 ...
- Java中hashCode方法的理解以及此小结的总结练习(代码)
笔记: “散列码”就是用来把一堆对象散到各自的队列里去的一种标识码. 举个形象一点的例子,一年有 365 天,从 1 编号到 365,下面我定义一种编码方法,每个人按照他生日那天的编号作为他的标识码, ...
- java判断当前系统是win还是linux
private static final boolean isWin = System.getProperty("os.name").toLowerCase().contains( ...
- liunx安装和部署nacos配置中心
1.下载https://github.com/alibaba/nacos/releases nacos-server-1.3.1.tar.gz 源码包2.上传到liunx服务器 /usr/lo ...
- 羞羞的Python模块包
目录 一.pip 二.pip常用命令 三.No module 'xxxxx' 四.写在最后 前言 写Python代码的时候,经常会遇到包的问题,但是都是遇到一次,搜索一次,解决了.下一次还是同样的 ...
- CCNA - Part12 - 路由协议 (1) - 静态路由,动态路由 RIP
路由器 在之前关于路由器的介绍中,我们知道它是网络互联的核心设备,用于连接不同的网络,在网络之间转发 IP 数据报.对于路由器来说,路由表是其内部最为重要的构成组件.当路由器需要转发数据时,就会按照路 ...
- 浅谈CSRF(Cross-site request forgery)跨站请求伪造
本文目录 CSRF是什么 CSRF攻击原理 CSRF攻击防范 CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack” ...