一、上下文及问题
1、基本原则
系统与其他外部系统交互,有时候操作比较复杂,需要一个防腐层来增强本系统与其他系统的耦合性,对本系统封装一些对外操作的细节,达到简化的目的。
符合最少知识原则,即Least Knowledge Principle,也成为迪米特原则,Law of Demeter。
2、定义
为子系统中的一组接口提供一个一直的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
(1)界面:从一个组件外部来看这个组件,能够看到什么,就是这个组件的界面,即外观。
比如,你从一个类的外部来看这个类,那么这个类的public方法就是这个类的外观;
比如,你从一个模块外部来看这个模块,那么这个模块对外的接口就是这个模块的外观。
(2)接口:外部和内部交互的一个通道,通常是指一些方法,可以是类方法,也可以是interface方法
二、常见场景
1、系统对外部系统调用的Facade,内部系统只依赖于Facade的方法,其里头再调用外部接口,达到防腐的目的,也达到了屏蔽一些外部接口的调用细节,比如封装异常,分步调用等
2、EJB的Session Facade,对客户端屏蔽了远程调用操作,减少客户端与服务对象之间的依赖程度,把底层服务对象的接口和它们之间的复杂依赖交互通过Facade隐藏起来。
三、解决方法
外观模式的目的不是给子系统添加新的功能接口,而是为了让外部减少与子系统内部多个模块的交互,松散耦合,从而让外部能够更简单地使用子系统。
但是外观模式不阻止客户端直接调用子模块的功能,它只是提供了一个缺省的功能实现。对外屏蔽子系统: 如果把Facade实现成为接口,还附带一个功能,就是能够有选择性地暴露接口的方法,尽量减少模块对子系统外提供的接口方法。
四、抽象模型
五、代码实例
1、模块
/**
* A模块
*/
public interface AModuleApi {
/**
* 示意方法,A模块对外的一个功能方法
*/
public void testA();
}
public class AModuleImpl implements AModuleApi{
public void testA() {
System.out.println("现在在A模块里面操作testA方法");
}
}
/**
* B模块
*/
public interface BModuleApi {
public void testB();
}
public class BModuleImpl implements BModuleApi{
public void testB() {
System.out.println("现在在B模块里面操作testB方法");
}
}
/**
* C模块
*/
public interface CModuleApi {
public void testC();
}
public class CModuleImpl implements CModuleApi{
public void testC() {
System.out.println("现在在C模块里面操作testC方法");
}
}
2、Facade
public class Facade {
//被委托的对象
private ClassA a = new ClassA();
private ClassB b = new ClassB();
private ClassC c = new ClassC();
//提供给外部访问的方法
public void methodA(){
this.a.doSomethingA();
}
public void methodB(){
this.b.doSomethingB();
}
public void methodC(){
this.c.doSomethingC();
}
}
3、Client
public class Client {
public static void main(String[] args) {
// //不用Facade,需要自己跟多个模块交互
// AModuleApi a = new AModuleImpl();
// a.testA();
// BModuleApi b = new BModuleImpl();
// b.testB();
// CModuleApi c = new CModuleImpl();
// c.testC();
//
// System.out.println("使用Facade----------------------〉");
//使用了Facade
new Facade().test();
}
}
来源:oschina
链接:https://my.oschina.net/u/1383356/blog/282753