11、外观模式(Facade Pattern)
1. 外观模式
1.1 简介
Facade模式要求一个子系统的外部与其内部的通信必须通过一个统一的Facade对象进行。Facade模式提供一个高层次的接口,使得子系统更易于使用。
从客户程序的角度来看,Facade模式不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种程度上也达到了一种“解耦”的效果——内部子系统的任何变化不会影响到Façade接口的变化。
注意区分Façade模式、Adapter模式、Bridge模式与Decorator模式。Façade模式注重简化接口,Adapter模式注重转换接口,Bridge模式注重分离接口(抽象)与其实现,Decorator模式注重稳定接口的前提下为对象扩展功能。
Facade的两种形式:
- 类内实现额外非接口定义方法的隐藏
- 对一组接口方法封装为一个提供对外服务
1.2 方法隐藏示例
对外接口FacadeService:
public interface FacadeService {
public void a();//这个方法是给外部调用的
}
实现类FacadeServiceImpl:
public class FacadeServiceImpl implements FacadeService {
public void a() {
System.out.println("这是给外部调用的");
}
public void b() {
System.out.println("这是给内部调用的");
}
}
a是给外部调用用的,此时可以给外部调用。但是b是给内部调用的,我们不希望给外部调用,此时可以怎么做呢?两种方式,一种是调整b方法的访问权限为private;另一种即Facade模式。
** FacadeServiceImplForOut:**
public class FacadeServiceImplForOut implements FacadeService {
private FacadeService facadeService;
public FacadeServiceImplForOut(FacadeServiceImpl facadeService){
this.facadeService=facadeService;
}
public void a() {
facadeService.a();
}
}
调用:
public class FacadeServiceMain {
public static void main(String[] args) {
FacadeServiceImpl facadeService = new FacadeServiceImpl();
FacadeServiceImplForOut fout = new FacadeServiceImplForOut(facadeService);
fout.a();
}
}
facade提供了一个供外部client调用的Facade层,由其组织调用真正的业务层,对于调用client来说,真正的业务层对他来说是透明的,这样做的好处是让调用层client和真正的业务层解耦,同时在Facade层也可以做更多的事情,比如上面的屏蔽client不该访问到的方法等等。
1.3 接口方法封装示例
我们把一个很文件的文件,放在了第二抽屉里,而第二个抽屉的钥匙放在了第一个抽屉里,我们要想取出这个文件,需要打开第一个抽屉拿到钥匙,然后打开第二个抽屉取出文件。
抽屉1DrawerOne:
class DrawerOne {
public void open(){
System.out.println("第一个抽屉被打开了");
getKey();
}
public void getKey(){
System.out.println("得到第二个抽屉的钥匙");
}
}
抽屉2 DrawerTwo:
class DrawerTwo{
public void open(){
System.out.println("第二个抽屉被打开了");
getFile();
}
public void getFile(){
System.out.println("得到这个重要文件");
}
}
调用示例:
public static void main(String []args){
DrawerOne darwerOne=new DrawerOne();
DrawerTwo darwerTwo=new DrawerTwo();
darwerOne.open();
darwerTwo.open();
}
** DrawerFacade:**
class DrawerFacade{
DrawerOne darwerOne=new DrawerOne();
DrawerTwo darwerTwo=new DrawerTwo();
public void open(){
darwerOne.open();
darwerTwo.open();
}
}
Facade调用示例:
public static void main(String []args){
DrawerFacade drawer=new DrawerFacade();
drawer.open();
}
1.4 使用场景
Facade模式主要适用于以下几种情况:
- 不需要使用一个复杂系统的所有功能,而且可以创建一个新的类,包含访问系统的所有规则。如果只需要使用系统的部分功能,那么你为新类所创建的API将比原系统的API简单的多。
- 希望封装或者隐藏系统原系统。
- 希望使用原系统的功能,而且还希望增加一些新的功能。
- 编写新类的成本小于所有人学会使用或者未来维护原系统上所需的成本。