一、外观模式定义
外观模式又称为门面模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便。
二、外观模式的结构和说明
不用外观模式的情况下,Client需要跟子系统的多个模块进行交互,这就要求Client对各个模块都比较了解,这种情况耦合度较高,并且对子系统的调用也比较复杂。
使用外观模式的情况下,Facade对子系统内的模块进行了封装。Client直接跟Facade层进行交互,无需关心各个模块是怎么实现的,减少了跟各个模块的交互,松散耦合,使调用变得更简单。
三、外观模式示例
假设有这样一个需求:我们需要根据数据库表,动态的生成对应的Controller、Service、Dao层基本增删改查代码。
Controller层生成器模块
/**
* Controller层生成器
*/
public class ControllerGenerator {
/**
* 生成Controller层代码文件
*/
public void generator(){
System.out.println("生成文件:Controller.java");
}
}
Service层生成器模块
/**
* Service层生成器
*/
public class ServiceGenerator {
/**
* 生成Service层代码文件
*/
public void generator(){
System.out.println("生成文件:Service.java");
}
}
Dao层生成器模块
/**
* Dao层生成器
*/
public class DaoGenerator {
/**
* 生成Dao层代码文件
*/
public void generator(){
System.out.println("生成文件:Dao.java");
}
}
以上是子系统的各个模块,接下来定义外观层模块
外观层模块
/**
* 定义生成代码的外观层
*/
public class GenetatorFacade {
/**
* 私有构造器
* 外观层一般只是对子系统各个模块的一个封装和组合,通常可以实现成单例,或者直接将方法定义为静态方法
*/
private GenetatorFacade() {
}
/**
* 生成需要的代码文件(对子系统各模块功能的包装)
*/
public static void genetator(){
// 生成Controller层代码文件
new ControllerGenerator().generator();
// 生成Service层代码文件
new ServiceGenerator().generator();
// 生成Dao层代码文件
new DaoGenerator().generator();
}
}
以上,外观模式的结构就已经定义好了,下边我们来模拟一下使用。
public class Client {
public static void main(String[] args) {
// 生成代码
GenetatorFacade.genetator();
}
}
执行main方法后,得到下边的输出:
生成文件:Controller.java
生成文件:Service.java
生成文件:Dao.java
四、外观模式的优缺点
优点:
- 松散耦合。 外观模式松散了客户端与子系统之间的耦合关系,使子系统模块更容易扩展和维护。
- 简单易用。 客户端不需要了解子系统内部各模块的具体实现,只要跟外观层交互,委托外观层去实现即可。
- 更好的划分访问层次。 子系统中有些方法是对系统外的,有些方法是系统内部使用的。通过外观层将对系统外的暴露出去,而将对内的隐藏,这样防止客户端发现一些不需要它知道的方法,造成迷惑和“接口污染”。
五、外观模式的应用场景
- 如果访问的子系统很复杂,增加外观模式提供一个简单的调用接口。
- 如果希望客户端和子系统之间实现松耦合,可以考虑用外观模式将它们隔离,从而提供子系统的独立性和可移植性。