本篇学习的是门面模式,又称外观模式,个人感觉还是觉得门面模式比较形象,是一种结构型模式。
一、引出模式
在生活中,比如我们准备自己配一台电脑,一种解决方案就是自己去电子市场一家一家的去询问,去购买,无疑这样是很浪费时间和精力的,另外一种解决方案就是直接去找一家装机公司,你把需求告诉它,它自然就会把相应的机器组装给你,这样你就只要知道装机公司就行,省了中间许多环节。这时的装机公司,我们可将其称为门面(Facade).
那我们将上面生活例子抽象一下,将电子市场看作一个系统,我们看作客户端。客户端为了完成某项功能,需要使用到系统中的许多模块,比如A模块,B模块和C模块。对于客户端来说,他就必须知道A、B、C三个模块的功能,还要知道应该如何组织这三种模块才能完成功能。这样就很大程度的违反了最少知识原则。如果现在我们提供了一种功能,将系统中的A、B、C三个模块的功能进行封装,客户端直接调用这个封装的功能,客户端就不用那么麻烦了。这个封装的功能就是Façade。
二、认识模式
1.模式定义
为子系统中的一组接口提供一个一致的界面,Façade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
在这里“界面”和“接口”要解释一下。
界面:这里的"界面"是指从一个组件外部来看这个组件,比如从一个类的外部看这个类,我们只能看到Public属性或方法,同理,我们从一个组件外部来看这个组件,我们只能看到这个组件公开的接口,而看不到该组件的内部实现。
接口:这里的接口是指组件外部与内部交互的一个通道,一般是一些方法。
用大白话来讲就是:将子系统中的一些方法提取到一个类中并将其封装,客户端只需要使用这个封装的类中的方法就可以间接使用子系统中的方法了。这个类就是Façade类。
2.解决思路
门面模式就是通过引用一个门面类,在这个类中定义客户端需要的一些简单方法,然后在这些个方法中在通过该门面类去调用内部的多个模型进行实现所需功能,这样客户端只需与门面类交互即可。
3.模式结构
1) Façade
定义子系统的多个模块对外的高层 接口,通常需要调用内部多个模块,从而将请求转调给适合的子系统对象。
2) 模块
接受Façade对象的委派,真正实现功能,各模块直接可能相互协作。
Façade对象是需要知道各个模块的,但是各个模块是不必知道Façade对象的。
4.示例代码
class Program { static void Main(string[] args) { Facade facade = new Facade(); facade.Test(); Console.ReadKey(); } } public class Facade { public void Test() { IAModuleApi aapi=new AModuleApi(); aapi.TestA(); IBModuleApi bapi=new BModuleApi(); bapi.TestB(); ICModuleApi capi = new CModuleApi(); capi.TestC(); } } public interface IAModuleApi { void TestA(); } public class AModuleApi:IAModuleApi { public void TestA() { Console.WriteLine("使用了AModuleApi"); } } public interface IBModuleApi { void TestB(); } public class BModuleApi : IBModuleApi { public void TestB() { Console.WriteLine("使用了BModuleApi"); } } public interface ICModuleApi { void TestC(); } public class CModuleApi : ICModuleApi { public void TestC() { Console.WriteLine("使用了CModuleApi"); } }
三、理解模式
1.门面模式的目的
门面模式的目的不是给子系统添加一个新的功能接口,而是为了减少外部与子系统内多个模块进行交互,松散耦合,从而让外部能够更简单的使用子系统。
需要再次强调的是,门面模式是负责组合子系统已有的功能来实现外部的需要,而不是添加新的实现。
2.使用门面和不使用门面到底差多少
很多人觉得,门面模式只不过是将原来客户端的代码封装到了Façade里面了,也没多大区别嘛?
前面一句说的是非常对的,当时使用的门面模式后,它们的本质发生了颠覆性的变化。
第一点,它相当于一扇窗口,屏蔽了外部客户端和系统内部模块的交互,从而是A、B、C模块组合成了一个整体,至此,客户端不必知道我要先谁,再找谁,你只需要知道找这个窗口就能办理手续了。这样,不但方便客户端的调用,而且封装了系统内部的细节功能。
第二点,Façade的功能可以被很多客户端调用。
3.门面模式提供了缺省的功能实现。
随着系统越来越大,Façade中的方法也会越来越多,我们可以在Façade类中封装外部最常用的,最复杂的功能,至于其他功能,让客户端绕过Façade直接对内部子系统进行调用。
4.Façade实现
1)对于一个子系统来说,Façade类,无需太多,我们可以将其实现为单例,也可以将它定义成一个静态类,当作工具类来使用。
2)当然我们还可以将Façade实现成为一个Interface接口,这样会增加系统的复杂程度,因为你需要一个工厂来多去Façade的接口对象。
这样做的好处就是能够有选择性地暴露接口的方法,尽量减少模块对子系统外提供的接口方法。
5.模式的优点
1) 松散耦合
2) 简单易用
3) 更好的的划分访问的层次
6.何时使用门面模式
1) 为一个复杂子系统提供一个简单接口
2) 提高子系统的独立性
3) 在层次化结构中,可以使用Facade模式定义系统中每一层的入口。
7.模式小结
门面模式的本质就是:封装交互,简化调用。
Facade封装了子系统外部与子系统内部多个模块的交互过程,从而简化了外部的调用