1.概述
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统的更容易使用。
2.角色
1)外观(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的子系统的功能和责任。
2)子系统角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被外观角色调用。
3.优缺点
1)它对客户屏蔽了子系统细节,减少了客户需要处理的对象的数目,使得子系统使用起来更加方便。
2)实现了子系统与客户之间的解耦,这样子系统变化只会影响到Facade,而不会影响到客户端。
3)Facade也可以使用在子系统内部的层与层之间。
4)更好的划分访问层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到外观中,这样既方便客户端使用,也很好的隐藏了内部的细节。
5)Facade并不会限制客户端使用子系统,客户端也可以绕过Facade,直接访问子系统通过外观对象来组织细粒度的服务的调用,外观对象提供给外部应用程序以使用的服务,而具体的调用细粒度的过程则被外观对象给封装起来,当然这个过程就是封装变化的部分,而将变化的部分与应用程序进行隔离,无疑对程序的易用性和可维护性都是很大的提高。
4.适用情况
1)为复杂的子系统提供一个简单的接口;
2)客户程序与抽象类的实现部分之间存在着很大的依赖性;
3)构建一个层次结构的子系统时,适用外观模式定义子系统中每层的入口点。
5.与其他模式的区别
1)与中介者模式的区别
中介者模式是让两个类不直接发生关系,而是通过中介者联系,中介者并不偏向于任一方,双方通过中介者互相和另一方发生关系,关系是双向的
门面模式也是让两个类不直接发生关系,但是门面偏向于某一方,另一方通过门面和某一方发生关系,但某一方不一定甚至不会通过门面和另一方发生关系,也就是关系偏向于单向关系
2)与装饰模式的区别
装饰模式和外观模式很大的分别就是外观从架构的角度去看待整个系统。
装饰是两个完全分开的部分的实现,即功能和对象同一等级,而功能是动态的,可以随时附加给对象,同时也可以撤销,达到分开隔离的处理效果和动态选用的功能,甚至可以将功能排列组合,动态分布。
总的来说,Facade模式、Adapter模式、Bridge模式与Decorator模式的区别在于:Facade模式注重简化接口,Adapter模式注重转换 接口,Bridge模式注重分离接口(抽象)与其实现,Decorator模式注重稳定接口的前提下为对象扩展功能。
5.实现代码
1)例一:
《大话设计模式C++版》
1 #include<iostream> 2 #include <string> 3 using namespace std; 4 5 class SubSysOne 6 { 7 public: 8 void MethodOne() 9 { 10 cout<<"方法一"<<endl; 11 } 12 }; 13 14 class SubSysTwo 15 { 16 public: 17 void MethodTwo() 18 { 19 cout<<"方法二"<<endl; 20 } 21 }; 22 23 class SubSysThree 24 { 25 public: 26 void MethodThree() 27 { 28 cout<<"方法三"<<endl; 29 } 30 }; 31 32 //外观类 33 class Facade 34 { 35 private: 36 SubSysOne* sub1; 37 SubSysTwo* sub2; 38 SubSysThree* sub3; 39 public: 40 Facade() 41 { 42 sub1 = new SubSysOne(); 43 sub2 = new SubSysTwo(); 44 sub3 = new SubSysThree(); 45 } 46 ~Facade() 47 { 48 delete sub1; 49 delete sub2; 50 delete sub3; 51 } 52 53 void FacadeMethod() 54 { 55 sub1->MethodOne(); 56 sub2->MethodTwo(); 57 sub3->MethodThree(); 58 } 59 }; 60 61 //客户端 62 int main() 63 { 64 Facade* test = new Facade(); 65 test->FacadeMethod(); 66 return 0; 67 }
2)例二:
http://www.xue163.com/182/6/1826151.html
1 #include "stdafx.h" 2 #include <iostream> 3 using namespace std; 4 5 class AnalysisApp{ 6 public: 7 void AnalysisDoc() 8 { 9 cout << "Complete Document!" << endl; 10 } 11 }; 12 13 14 class CodeApp 15 { 16 public: 17 void DesignCode() 18 { 19 cout << "Complete Code!" << endl; 20 } 21 }; 22 23 24 class TestApp 25 { 26 public: 27 void TestExample() 28 { 29 cout << "Complete Test!" << endl; 30 } 31 }; 32 33 34 class FacadeApp 35 { 36 private: 37 AnalysisApp *analysisApp; 38 CodeApp *codeApp; 39 TestApp *testApp; 40 public: 41 FacadeApp(){ 42 analysisApp = new AnalysisApp(); 43 codeApp = new CodeApp(); 44 testApp = new TestApp(); 45 } 46 void ShowApp(){ 47 analysisApp->AnalysisDoc(); 48 codeApp->DesignCode(); 49 testApp->TestExample(); 50 } 51 }; 52 53 class Boss 54 { 55 public: 56 void GetAppResult() 57 { 58 FacadeApp *facadeApp = new FacadeApp(); 59 facadeApp->ShowApp(); 60 } 61 }; 62 63 int _tmain(int argc, _TCHAR* argv[]) 64 { 65 Boss *boss = new Boss(); 66 boss->GetAppResult(); 67 cin.get(); 68 return 0; 69 }