Facade
别名:门面模式
定义
提供一个统一的接口,用来访问子系统中的一群接口。
应用场景
1.如果你需要一个指向复杂子系统的直接接口,且该接口的功能有限,则可以使用外观模式
子系统通常会随着时间的推进变得越来越复杂。由于创建了许多类,其所需的配置和样板代码数量也会许多。
2.如果需要将子系统的组织为多层结构,可以使用外观
创建外观来定义子系统中各层次的入口。你可以要求子系统仅用外观来进行交互,来减少子系统之间的耦合。
实现方法
1.当该接口能让客户端代码独立于众多子系统类,则可以考虑在现有子系统的基础上提供一个更简单的接口。
2.在一个新的外观类中声明并实现该接口。外观应将客户端代码的调用重定向到子系统中的相应对象处。如果客户端代码未对子系统进行初始化,也没有对其后续生命周期进行管理,那么外观必须完成此类工作。
3.必须确保所有客户端代码仅通过外观来与子系统进行交互。此后客户端将不会受到任何由系统代码修改而造成的影响。eg:子系统升级后,你只需改外观的代码即可
优缺点
优点:
可以使代码独立于复杂子系统,简化调用过程
缺点:
外观可能成为程序中所有类都耦合的上帝对象
结构
UML图
classDiagram
Client --> Facade
Facade --> AdditionalFacade
Facade..>Subsystem_more
AdditionalFacade..>Subsystem_more
class Facade{
-linksToSubsystemObjects
-optionalAddtionFacade
+subsystemOperation()
}
class AdditionalFacade{
...
+anotherOperation()
}
参与者
1.外观( Facade )提供了一种访问特定子系统功能的便捷方式,其了解如何重定向客户端请求, 知晓如何操作一切活动部件。
2.创建附加外观(Additional Facade)类可以避免多种不相关 的功能污染单一外观, 使其变成又一个复杂结构。 客户端和 其他外观都可使用附加外观。
3.复杂子系统(Complex Subsystem)由数十个不同对象构成。 如果要用这些对象完成有意义的工作, 你必须深入了解子系 统的实现细节, 比如按照正确顺序初始化对象和为其提供正确格式的数据。
子系统类不会意识到外观的存在, 它们在系统内运作并且相 互之间可直接进行交互。
4.客户端(Client)使用外观代替对子系统对象的直接调用。
通用写法
public class Facade {
private Map<String,Object> linksToSubsystemObjects;
private AdditionalFacade optionalAdditionalFacade;
public void subsysteamOperation(){
SubsystemA subsysteamA = new SubsystemA();
subsysteamA.opera();
SubsystemZ subsysteamZ = new SubsystemZ();
subsysteamZ.opera();
}
}
public class AdditionalFacade {
private Map<String,Object> linksToSubsystemObjects;
private AdditionalFacade optionalAdditionalFacade;
public void anotherOperation(){
SubsystemB subsysteamB = new SubsystemB();
subsysteamB.opera();
SubsystemZ subsysteamZ = new SubsystemZ();
subsysteamZ.opera();
}
}
public class SubsystemA {
public void opera(){
System.out.println("subsystemA Come");
}
}
public class SubsystemB {
public void opera(){
System.out.println("subsystemB Come");
}
}
public class SubsystemZ {
public void opera(){
System.out.println("subsystemZ Come");
}
}
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.subsysteamOperation();
facade.setOptionalAdditionalFacade(new AdditionalFacade());
facade.getOptionalAdditionalFacade().anotherOperation();
}
}