读书笔记-设计模式-可复用版-Facade 外观模式
读书笔记-设计模式-可复用版-Facade 外观模式
这两天在使用PureMVC Framework,会经常和Facade进行打交道,很早之前写过一篇这方面的文章来分析框架,最近和同事在讨论这套框架,还是挺受益的
本来想着按照类型的划分去复习设计模式,现在改变一下,先去复习当前用到的的设计模式,这样会更好的理解工作中目前正在用的这些
Facade->Mediator->Command->Observer 后面大致会是这个顺序
-------
意图:
关键描述:与子系统(system)进行交互
为子系统中的一组接口(或者说是子系统subsystem),提供一个一致的,简单的接口,以降低交互的复杂度。
上一篇介绍关于Proxy时,引用了wikipedia的解释,刚才查了一下Facade,依然是非常清晰,比书里要清晰明了得多,尤其是提供了更加清晰的UML和时序图:
https://en.wikipedia.org/wiki/Facade_pattern
这里重点是“降低复杂度“
通过使用Facade,可以提高代码的可读性和易用性。
readability and usability
当我们去和某个或是某几个子系统进行交互的时候,通常子系统是复杂或是难以理解的,有若干个子类,而且相互之间的依赖关系通常也比较重,如果我们直接和子系统中的某些接口进行交互,依赖关系会变得比较复杂,通过Facade设计模式,提供一个简单的,一致的接口,可以降低这种依赖的复杂度,并且让代码更具有可读性和易用性。
可以想象下:
我现在有三个客户类,子系统中有5个接口,在没有Facade模式的情况下,
调用的关系可能如下:
实际项目通常要比这种情况更加的复杂,这种调用关系变得很杂乱,如果这时候我希望在调用子系统的时候,执行一些附加的逻辑,这层附加的逻辑不属于子系统本身的,那么可以想象,你将会修改N次调用的地方......
降低与子系统间的通信和相互依赖的复杂度。
如图:
通过添加一个Facade类,降低了外部与子系统通信的复杂度。
下面是wikipedia上的UML&时序图:
client不直接和subsystem进行交互, 通过facade来处理。
在PureMVC Framework:
在截图的最下面,Mediator ,Command,Proxy,他们就是一套子系统subsystem
分别对应着MVC,但他们的Register和Retrieve均是通过Facade提供的一个统一的接口进行交互通信,外部使用时,只需要通过Facade来与subsystem交互即可。
Facade实现了子系统和客户之间的松耦合关系,子系统内部的功能组件往往是紧耦合的,松耦合的关系使得子系统的组件变化不会影响到它的客户。况且随着需求,子系统的变化可能会越来越庞大和复杂。
Facade模式有助于建立层次结构系统,也有助于对对象之间的依赖关系分层。
在实现层面,用抽象类实现Facade ,而它的子类对应于不同的子系统实现,这可以进一步降低客户与子系统的耦合度。这样,客户就可以通过抽象的Facade类接口与子系统通讯,这种“抽象耦合”关系使得客户不知道(不确定,任何子类)它使用的是子系统哪一个实现的。
Facade通常使用Singleton单例模式实现。一组子系统,只需要一个Facade即可。
最后直接贴上wikipedia提供的两个sample code,很清晰的例子:
namespace DesignPattern.Facade
{
classSubsystemA
{
publicstring OperationA1()
{
return"Subsystem A, Method A1\n";
}
publicstring OperationA2()
{
return"Subsystem A, Method A2\n";
}
}
classSubsystemB
{
publicstring OperationB1()
{
return"Subsystem B, Method B1\n";
}
publicstring OperationB2()
{
return"Subsystem B, Method B2\n";
}
}
classSubsystemC
{
publicstring OperationC1()
{
return"Subsystem C, Method C1\n";
}
publicstring OperationC2()
{
return"Subsystem C, Method C2\n";
}
}
publicinterfaceIFacade
{
void Operation1();
void Operation2();
}
publicclassFacade:IFacade
{
privatereadonlySubsystemA a = newSubsystemA();
privatereadonlySubsystemB b = newSubsystemB();
privatereadonlySubsystemC c = newSubsystemC();
publicvoid Operation1()
{
Debug.Log("Operation 1\n" +
a.OperationA1() +
b.OperationB1() +
c.OperationC1());
}
publicvoid Operation2()
{
Debug.Log("Operation 2\n" +
a.OperationA2() +
b.OperationB2() +
c.OperationC2());
}
}
}
第二个例子是关于汽车,CarModel,CarEngine,CarAccessories,通过Facade提供一致的,简单的接口:
namespace DesignPattern.Facade.Sample
{
// The 'Subsystem ClassA' class
classCarModel
{
publicvoid SetModel()
{
Debug.Log(" CarModel - SetModel");
}
}
/// <summary>
/// The 'Subsystem ClassB' class
/// </summary>
classCarEngine
{
publicvoid SetEngine()
{
Debug.Log(" CarEngine - SetEngine");
}
}
// The 'Subsystem ClassC' class
classCarBody
{
publicvoid SetBody()
{
Debug.Log(" CarBody - SetBody");
}
}
// The 'Subsystem ClassD' class
classCarAccessories
{
publicvoid SetAccessories()
{
Debug.Log(" CarAccessories - SetAccessories");
}
}
publicinterfaceIFacade
{
void CreateCompleteCar();
}
// The 'Facade' class
publicclassCarFacade:IFacade
{
privatereadonlyCarAccessories accessories;
privatereadonlyCarBody body;
privatereadonlyCarEngine engine;
privatereadonlyCarModel model;
publicCarFacade()
{
accessories = newCarAccessories();
body = newCarBody();
engine = newCarEngine();
model = newCarModel();
}
publicvoid CreateCompleteCar()
{
Debug.Log("******** Creating a Car **********");
model.SetModel();
engine.SetEngine();
body.SetBody();
accessories.SetAccessories();
Debug.Log("******** Car creation is completed. **********");
}
void Start()
{
DesignPattern.Facade.Sample.IFacade facade = new
DesignPattern.Facade.Sample.CarFacade();
facade.CreateCompleteCar();
}
}
}
除此之外,还想到了一另外一个现实中的例子,银行办理业务:
银行的业务是非常得复杂的,比如存,取款, 挂失,开卡,信息变更等等
但我们不需要去找特定的业务,我们都是通过银行提供给我们的业务办理窗口,通过这个窗口,可以统一的处理上面提到的不同需求(你的不同需求,都由这个窗口帮你处理 )。
通过这个“窗口”,极大的方便了客户,降低了业务办理的复杂度。否则流程就会很复杂,效率很缓慢。
2019.6.21 12:42 天通苑东二区 家中