外观模式:
外观模式(Facade),他隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口。这种类型的设计模式属于结构性模式。为子系统中的一组接口提供了一个【高层的】统一的访问接口,这个接口使得子系统更容易被访问或者使用。
结构:
1).门面角色【Facade】:外观模式的核心。它被客户角色调用,它熟悉子系统的功能。内部根据客户角色的需求预定了几种功能的组合。
2).子系统角色【模块A,B,C的组合】:实现了子系统的功能。它对客户角色和Facade时未知的。它内部可以有系统内的相互交互,也可以由供外界调用的接口。
3).客户角色【Client】:通过调用Facede来完成要实现的功能。
源代码:
SubSystem类:
public class SubSystemA {
public void methodA(){
System.out.println("进入A。。。");
}
}
class SubSystemC{
public void methodC(){
System.out.println("进入C。。。");
}
}
class SubSystemB{
public void methodB(){
System.out.println("进入B。。。");
}
}
Facade类:
public class Facade {
private SubSystemA a = new SubSystemA();
private SubSystemB b = new SubSystemB();
private SubSystemC c = new SubSystemC();
public void method(){
a.methodA();
b.methodB();
c.methodC();
}
}
Client类:
public class Client {
public static void main(String[] args){
Facade facade = new Facade();
facade.method();
}
}
从中,我们可以发现Facade类作为外观模式的核心,不仅方便了客户端的调用,而且还成功的封装了系统内部的实现细节。
应用实例:
代码生成器是工作中常用到的,其中就很好的表达了外观模式的优点:
ConfigModel类:
public class ConfigModel {
//是否需要生成表现层 ,默认为true
private boolean needGenPresentation = true;
//是否需要生成逻辑层,默认为true
private boolean needGenBusiness = true;
//是否需要生成Dao,默认为true
private boolean needGenDao = true;
public boolean isNeedGenPresentation(){
return needGenPresentation;
}
public void setNeedGenPresentation(boolean needGenPresentation){
this.needGenPresentation = needGenPresentation;
}
public boolean isNeedGenBusiness(){
return needGenBusiness;
}
public void setNeedGenBusiness(){
this.needGenBusiness = needGenBusiness;
}
public void setNeedGenBusiness(boolean needGenBusiness){
this.needGenBusiness = needGenBusiness;
}
public boolean isNeedGenDao(){
return needGenDao;
}
public void setNeedGenDao(boolean needGenDao){
this.needGenDao = needGenDao;
}
}
ConfigManager类:
/**
* 配置管理,负责读取配置文件,并把配置文件的内容设置到配置Model中,是个单例
* @Title:
* @Description:TODO
* @Date:2018-1-19下午10:04:58
*/
public class ConfigManager {
private static ConfigManager manager = null;
private static ConfigModel cm = null;
private ConfigManager(){
}
public static ConfigManager getInstance(){
if(manager == null){
manager = new ConfigManager();
//读取配置文件,把值设置到configModel中
cm = new ConfigModel();
}
return manager;
}
/**
* 获取配置的数据
* @return配置的数据
*/
public ConfigModel getConfigData(){
return cm;
}
}
Dao类:
public class Dao {
public void generate(){
///1.从配置管理里获得相应的配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenDao()){
System.out.println("正在生成数据层的代码文件");
}
}
}
Presentation类:
public class Presentation {
public void generate(){
//1.从配置管理里面获取相应配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenPresentation()){
//2.按照要求生成相应代码,并保存成文件
System.out.println("正在生成表现成代码文件");
}
}
}
Business类:
public class Business {
public void generate(){
//1.从配置管理里获取相应的配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenBusiness()){
//2.按照要求去生成相应的代码,并保存成文件
System.out.println("正在生成逻辑代码文件");
}
}
}
Facade类:
/*
* 代码生成子系统的外观对象
*/
public class Facade {
/*
* 客户端需要的,一个简单的调用代码生成的功能
*/
public void generate(){
new Presentation().generate();
new Business().generate();
new Dao().generate();
}
}
Client类:
public class Client {
public static void main(String[] args){
new Facade().generate();
}
}
输出:
正在生成表现成代码文件
正在生成逻辑代码文件
正在生成数据层的代码文件
由此我们可以看出:
Facade类 其实就是一个辅助工具类。一般是负责把客户端的请求转发给子系统内部各个模块进行处理,Facade的方法本省并不进行功能处理。Facade的方法实现只是实现一个功能的组合调用。
何时选用外观模式:
1.如果你希望称为一个复杂的子系统提供一个简单接口时,可以考虑使用外观模式。使用外观对象来实现大部分客户需要的功能,从而简化客户的使用。
2.如果想要客户程序和抽象类的实现部分松散耦合,可以考虑使用外观模式,用外观对象来将这个子系统与他的客户分离,从而提高子系统的独立性和可移植性
3.构建多层结构的系统,可以考虑使用外观模式,使用外观对象作为每层的入口,这样可以简化层间调用,也可以
松散层次之间的依赖关系。
【当然这些都是官方说法,其实自己也不是很懂。。。。哈哈,还需努力!】