读书笔记-设计模式-可复用版-Facade 外观模式

发表于2019-06-24
评论1 1.7k浏览

想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏策划行业精英群

361498939

读书笔记-设计模式-可复用版-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模式的情况下,

调用的关系可能如下:


 

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


 

实际项目通常要比这种情况更加的复杂,这种调用关系变得很杂乱,如果这时候我希望在调用子系统的时候,执行一些附加的逻辑,这层附加的逻辑不属于子系统本身的,那么可以想象,你将会修改N次调用的地方......


 

降低与子系统间的通信和相互依赖的复杂度。


 

如图:


 

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


 

通过添加一个Facade类,降低了外部与子系统通信的复杂度。


 

下面是wikipedia上的UML&时序图:


 

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


 


 

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


 

client不直接和subsystem进行交互, 通过facade来处理。


 

在PureMVC Framework:


 

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


 

在截图的最下面,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 天通苑东二区 家中

  • 允许他人重新传播作品,但他人重新传播时必须在所使用作品的正文开头的显著位置,注明用户的姓名、来源及其采用的知识共享协议,并与该作品在磨坊上的原发地址建立链接
  • 可对作品重新编排、修改、节选或者以作品为基础进行创作和发布
  • 可将作品进行商业性使用

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

游戏学院公众号二维码
腾讯游戏学院
微信公众号

提供更专业的游戏知识学习平台