`

外观模式1

 
阅读更多

3.1  场景问题

3.1.1  生活中的示例

外观模式在现实生活中的示例很多,比如:组装电脑,通常会有两种方案。

一个方案是去电子市场把自己需要的配件都买回来,然后自己组装,绝对DIY(Do It Yourself)。这个方案好是好,但是需要对各种配件都要比较熟悉,这样才能选择最合适的配件,而且还要考虑配件之间的兼容性。如图3.1所示:

 

图3.1  客户完全自己组装电脑

另外一个方案,就是到电子市场,找一家专业装机的公司,把具体的要求一讲,然后就等着拿电脑就好了。当然价格会比自己全部DIY贵一些,但综合起来这还算是个不错的选择,估计也是大多数人的选择。如图3.2所示:

 

图3.2  找专业的装机公司组装电脑

这个专业的装机公司就相当于本章的主角——Facade。有了它,我们就不用自己去跟众多卖配件的公司打交道,只需要跟装机公司交互就可以了,由装机公司去跟各个卖配件的公司交互,并组装好电脑返回给我们。

把上面的过程抽象一下,如果把电子市场看成是一个系统,而各个卖配件的公司看成是模块的话,就类似于出现了这样一种情况:客户端为了完成某个功能,需要去调用某个系统中的多个模块,把它们称为是A模块、B模块和C模块吧,对于客户端而言,那就需要知道A、B、C这三个模块的功能,还需要知道如何组合这多个模块提供的功能来实现自己所需要的功能,非常麻烦。

要是有一个简单的方式能让客户端去实现相同的功能多好啊,这样,客户端就不用跟系统中的多个模块交互,而且客户端也不需要知道那么多模块的细节功能了,实现这个功能的就是Facade。

3.1.2  代码生成的应用

考虑这样一个实际的应用:代码生成。

很多公司都有这样的应用工具,能根据配置生成代码。一般这种工具都是公司内部使用,较为专有的工具,生成的多是按照公司的开发结构来实现的常见的基础功能,比如增删改查。这样每次在开发实际应用的时候,就可以以很快的速度把基本的增删改查实现出来,然后把主要的精力都放在业务功能的实现上。

当然这里不可能去实现一个这样的代码生成工具,那需要整本书的内容,这里仅用它来说明外观模式。

假设使用代码生成出来的每个模块都具有基本的三层架构,分为:表现层、逻辑层和数据层,那么代码生成工具里面就应该有相应的代码生成处理模块。

另外,代码生成工具自身还需要一个配置管理的模块,通过配置来告诉代码生成工具,每个模块究竟需要生成哪些层的代码,比如:通过配置来描述,是只需要生成表现层代码呢,还是三层都生成。具体的模块示意如图3.3所示;

 

图3.3  代码生成工具的模块示意图

    那么现在客户端需要使用这个代码生成工具来生成需要的基础代码,该如何实现呢?

3.1.3  不用模式的解决方案

有朋友会想,开发一个这样的工具或许会比较麻烦,但是使用一下,应该不难吧,直接调用不就可以了。

在示范客户端之前,先来把工具模拟示范出来,为了简单,每个模块就写一个类,而且每个类只是实现一个功能,仅仅做一个示范。

(1)先看看描述配置的数据Model,示例代码如下:

/**

 * 示意配置描述的数据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 needGenPresentation) {

       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;

    }

}

(2)接下来看看配置管理的实现示意,示例代码如下:

/**

 * 示意配置管理,就是负责读取配置文件,

 * 并把配置文件的内容设置到配置Model中去,是个单例

 */

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();

           cm = new ConfigModel();

           //读取配置文件,把值设置到ConfigModel中去,这里省略了

       }

       return manager;

    }

    /**

     * 获取配置的数据

     * @return 配置的数据

     */

    public ConfigModel getConfigData(){

       return cm;

    }

}

(3)接下来就来看看各个生成代码的模块,在示意中,它们的实现类似,就是获取配置文件的内容,然后按照配置来生成相应的代码。分别看看它们的示意实现,先看生成表现层的示意实现,示例代码如下:

/**

 * 示意生成表现层的模块

 */

public class Presentation {

    public void generate(){

       //1:从配置管理里面获取相应的配置信息

       ConfigModel cm =

ConfigManager.getInstance().getConfigData();

       if(cm.isNeedGenPresentation()){

           //2:按照要求去生成相应的代码,并保存成文件

           System.out.println("正在生成表现层代码文件");

       }

    }

}

生成逻辑层的示意实现,示例代码如下:

/**

 * 示意生成逻辑层的模块

 */

public class Business {

    public void generate(){

       ConfigModel cm =

ConfigManager.getInstance().getConfigData();

       if(cm.isNeedGenBusiness()){

           System.out.println("正在生成逻辑层代码文件");

       }

    }

}

生成数据层的示意实现,示例代码如下:

/**

 * 示意生成数据层的模块

 */

public class DAO {

    public void generate(){

       ConfigModel cm =

ConfigManager.getInstance().getConfigData();

       if(cm.isNeedGenDAO()){

           System.out.println("正在生成数据层代码文件");

       }

    }

}

(4)此时的客户端实现,就应该自行去调用这多个模块了,示例代码如下:

public class Client {

    public static void main(String[] args) {

       //现在没有配置文件,就直接使用默认的配置,通常情况下,三层都应该生成,

//也就是说客户端必须对这些模块都有了解,才能够正确使用它们

       new Presentation().generate();

       new Business().generate();

       new DAO().generate();

    }

}

运行结果如下:

正在生成表现层代码文件

正在生成逻辑层代码文件

正在生成数据层代码文件

3.1.4  有何问题

仔细查看上面的实现,会发现其中有一个问题:那就是客户端为了使用生成代码的功能,需要与生成代码子系统内部的多个模块交互。

这对于客户端而言,是个麻烦,使得客户端不能简单的使用生成代码的功能。而且,如果其中的某个模块发生了变化,还可能会引起客户端也需要跟着变化。

那么如何实现,才能让子系统外部的客户端在使用子系统的时候,既能简单的使用这些子系统内部的模块功能,而又不用客户端去与子系统内的多个模块交互呢?

分享到:
评论

相关推荐

    8外观模式1

    在描述中提到的三个UML应用场景都体现了外观模式的核心价值。 1. **为一个复杂的子系统提供一个简单的接口**:当一个子系统包含众多类和接口,其内部结构复杂时,客户端可能难以理解和使用。外观模式通过创建一个高...

    c#代码介绍23种设计模式-11外观模式(附代码)

    1. 外观模式定义: 外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。使用外观模式时,我们创建了一个统一的类,用来包装子系统中一个或多个复杂的类, ...

    设计模式之外观模式

    外观模式(Facade Pattern)是设计模式中的一种结构型模式,它的主要目的是为了解耦系统,提供一个统一的入口,使得客户端可以更容易地使用复杂的子系统。在Java中,外观模式通常用于简化对复杂系统的访问,它创建了...

    设计模式之外观模式案例代码

    1. **定义**:外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。它封装了复杂的组件,提供了一个简洁的外部接口,让客户端代码可以更容易地与子系统交互。 2. **主要角色**: - **外观(Facade)...

    设计模式 - 外观模式(C++实例)

    1. **外观类(Facade)**:这是外观模式的核心,它提供了一个简单的接口,用于与客户端进行交互。外观类通常会包含子系统的引用,并负责调用子系统的方法。 2. **子系统类(Subsystem Classes)**:这些类实现了系统...

    设计模式外观模式PPT学习教案.pptx

    设计模式外观模式PPT学习教案 在软件设计中,外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口来访问子系统中的多个接口,从而简化了子系统的使用和维护。本节课程将详细介绍外观模式的...

    外观模式 Java实现 IDEA工程

    用外观模式实现下面这个抵押系统。 考虑这样一个抵押系统,当有一个客户来时,有如下几件事情需要确认: ...1、画出适合上述外观模式的类图 2、给出相关代码。用printf("")类似的方式表示相关的行为即可。

    设计模式-外观模式(讲解及其实现代码)

    1. **简化接口**:通过提供一个简单的接口,外观模式降低了客户端与复杂系统之间的交互难度。 2. **降低耦合**:客户端与子系统的耦合度降低,因为它们不再直接相互依赖,而是通过外观类进行间接通信。 3. **提高可...

    设计模式之适配器模式与外观模式demo

    适配器模式和外观模式是两种非常重要的设计模式,它们在实际项目中有着广泛的应用。本资源提供了一个关于这两种模式的实战示例,帮助我们更好地理解和应用它们。 适配器模式(Adapter Pattern)的主要目的是将两个...

    Android外观模式demo

    下面我们将详细探讨Android外观模式的概念、结构以及如何通过提供的"Android外观模式demo"进行实践。 外观模式的核心思想是提供一个统一的入口,隐藏系统的复杂性。在Android环境中,这通常意味着创建一个类,该类...

    外观模式.txt

    1. **系统有多个子系统或模块**:当一个系统由多个子系统或模块组成时,使用外观模式可以提供一个简单的统一接口。 2. **降低系统的复杂度**:通过定义一个高层接口来减少系统之间的依赖关系,从而降低系统的复杂度...

    设计模式--外观模式java例子

    1. **简化接口**:通过提供一个统一的接口,外观模式简化了客户端与复杂系统的交互。 2. **解耦**:客户端与子系统之间解耦,使得两者可以独立进行修改和扩展。 3. **提高可扩展性**:添加新的子系统或改变子系统的...

    C#设计模式-外观模式

    **外观模式(Facade Pattern)**是软件工程中一种常用的设计模式,它为复杂的子系统提供了一个简单的接口,使得客户端代码可以更容易地与这些子系统交互。在C#中,外观模式同样被广泛应用,以降低系统的复杂性,提高...

    java设计模式之外观模式

    **外观模式(Facade Pattern)**是软件设计模式中的一种结构型模式,它的主要目的是为了解耦复杂的系统,提供一个统一的接口,使得客户端可以更容易地使用这个系统。在这个模式中,外观类作为客户端与子系统之间的...

    大话设计模式之外观模式

    大话设计模式之外观模式 经典代码 C#类

    装饰、外观模式实例代码

    装饰模式和外观模式是软件设计模式中的两种重要结构模式,它们在实际开发中有着广泛的应用。下面我们将分别探讨这两种模式的原理、应用场景以及实例代码。 首先,装饰模式(Decorator Pattern)是一种行为设计模式...

    设计模式_外观模式示例代码

    外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于与一个复杂的子系统进行交互。这个接口简化了子系统的使用,使得客户端无需了解子系统内部的复杂性。在本示例中,电脑整机可以看作是...

Global site tag (gtag.js) - Google Analytics