外观模式(Facade)

来源:互联网 发布:python 输入矩阵 编辑:程序博客网 时间:2024/06/06 08:41
@@@模式定义:
为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,
这个接口使得这一子系统更加容易使用。


@@@练习示例: 
模拟一个代码生成工具,来生成一个三层架构(表现层、逻辑层、数据层)的代码。


@@@不用模式:
coder\ConfigModel.java                [描述配置的数据Model]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package coder;


/**
* 示意配置描述的数据Model,真实的配置数据会很多
*/
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 needGenPrasentation) {
this.needGenPresentation = needGenPresentation;
}


public boolean isNeedGenBusiness() {
return needGenBusiness;
}


public void setNeedGenBusiness(boolean needGenBusiness) {
this.needGenBusiness = needGenBusiness;
}


public boolean isNeedGenDAO() {
return needGenDAO;
}


public void setNeedGenDAO(boolean needGenDAO) {
this.needGenDAO = needGenDAO;
}
}


coder\ConfigManager.java               [配置管理]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package coder;


/**
* 示意配置管理,就是负责读取配置文件,
* 并把配置文件的内容设置到配置Model中去,是个单例
*/
public class ConfigManager {
private static ConfigManager manager = null;
private static ConfigModel   cm      = null;


private ConfigManager() {
   // 
}


public static ConfigManager getInstance() {
if (null == manager){
manager = new ConfigManager();
cm      = new ConfigModel();
// 读取配置文件,把值设置到ConfigModel中去,此处省略
}


return manager;
}


/**
* 获取配置的数据
* @return 配置的数据
*/
public ConfigModel getConfigData() {
return cm;
}
}


coder\Presentation.java                     [生成表现层的模块]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


package coder;


/**
* 示意生成表现层的模块
*/
public class Presentation {
public void generate() {
// 1. 从配置管理里面获取相应的配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenPresentation()) {
// 2. 按照要求去生成相应的代码,并保存成文件
System.out.println("正在生成表现层代码文件");
}
}
}


coder\Business.java                 [生成逻辑层的模块]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


package coder;


/**
* 示意生成逻辑层的模块
*/
public class Business {
public void generate() {
// 1. 从配置管理里面获取相应的配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenBusiness()) {
// 2. 按照要求去生成相应的代码,并保存成文件
System.out.println("正在生成逻辑层代码文件");
}
}
}


coder\DAO.java               [生成数据层的模块]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


package coder;


/**
* 示意生成数据层的模块
*/
public class DAO {
public void generate() {
// 1. 从配置管理里面获取相应的配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenDAO()) {
// 2. 按照要求去生成相应的代码,并保存成文件
System.out.println("正在生成数据层代码文件");
}
}
}




user\Client.java          [客户端实现]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


package user;


import coder.Presentation;
import coder.Business;
import coder.DAO;


public class Client {
public static void main(String[] args) {
/*
* 现在没有配置文件,直接使用默认配置,通常情况下,三层都应该生成
* 也就是说客户端必须对这些模块都了解,才能够正确使用它们
*/
new Presentation().generate();
new Business().generate();
new DAO().generate();
}
}


@@@存在问题:
客户端为了使用生成代码的功能,需要与生成代码子系统内部的多个模块交互。违反了LKP。
导致客户端使用代码生成功能时比较复杂,并且,如果其中某个模块发生变化后可能会导致客户端也需要随着其变化。


@@@使用模式:
代码生成模块中,新增一个Facade类,其他不变。
coder\Facade.java              [模块的外观]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


package coder;


/**
* 代码生成子系统的外观类
*/
public class Facade {
/**
* 客户端需要的,一个简单的调用代码生成的功能
*/
public void generate() {
new Presentation().generate();
new Business().generate();
new DAO().generate();
}
}


user\Client.java                [客户端实现]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


package user;


import coder.Facade;


public class Client {
public static void main(String[] args) {
// 使用Facade
new Facade().generate();
}
}


此时,客户端不再需要知道代码生成模块中的各个子模块,
只需要知道使用代码生成模块的外观类的generate方法来生成代码即可。
体现了最少知识原则,也是以客户为中心的做法。


@@@外观模式的实现:
(1)Facade通常可以实现成为一个单例;
(2)Facade也可以实现成为一个接口;
(3)Facade中的方法通常可以实现为静态方法;
(4)Facade中的方法一般只进行组合调用,其本身并不进行功能处理;


@@@外观模式的优点:
松散耦合
简单易用
更好地划分访问的层次


@@@外观模式的缺点:
过多的或者是不太合理的Facade容易让人迷惑。到底是调用Facade好呢,还是直接调用模块好。


@@@外观模式的本质:
封装交互,简化调用。


@@@外观模式体现的设计原则:

最少知识原则



原创粉丝点击