生活中的示例:组装电脑,如组装公司根据你的需求组装一个电脑(需要接触卖CPU、卖主板的)给你,这里的组装公司的角色就是外观模式。
分析将卖cpu等的电子市场视为一个系统,卖各个配件的视为模块,需求就变为:客户需要调用系统的各个模块,A,B,C模块,对于客户如果要知道A,B,C模块功能,并自己组装起来,很麻烦,引入Facade模式,客户无需知道各个模块功能,只需和外观模式打交道即可。
待解决的问题:表示层代码生成模块,逻辑层模块,数据层模块,配置管理模块(每个模块生成哪些层的代码),用户要调用系统的这些模块。
不使用设计模式的实现如下:
表示层:
package notusingmode;
/*
* 示意生成表示层的实现
*/
public class Presetation {
public void generate(){
//1,从配置管理里获取相应的配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenPresentation()){
//2,按照要求去生成相应的代码,并保存成文件
System.out.println("正在生成表示层代码文件");
}
}
}
package notusingmode;
//dao层
public class DAO {
public void generate(){
//1,从配置管理里获取相应的配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenDAO()){
//2,按照要求去生成相应的代码,并保存成文件
System.out.println("正在生成数据层代码文件");
}
}
}
package notusingmode;
//逻辑层
public class Business {
public void generate(){
//1,从配置管理里获取相应的配置信息
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenBusiness()){
//2,按照要求去生成相应的代码,并保存成文件
System.out.println("正在生成逻辑层代码文件");
}
}
}
package notusingmode;
/*
* 配置的数据模型,是否需要生成逻辑层、数据层等的代码
*/
public class ConfigModel {
private boolean needGenPresentation = true; //是否需要生成表示层
private boolean needGenBusiness = 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;
}
}
package notusingmode;
/*
* 配置管理的实现,就是负责读取配置文件,将配置文件内容设置到Model中去,是个单例模式
*/
public class ConfigManager {
private static ConfigManager manager = null;
private static ConfigModel cm = null;
private ConfigManager() {
}
public ConfigModel getConfigData() {
return cm; // 非静态方法可以使用静态变量,而静态方法必须使用静态变量
}
public static ConfigManager getInstance() {
if (manager == null) {
manager = new ConfigManager();
cm = new ConfigModel();
// 读取配置文件,把值设置到ConfigModel中去,这里省略了
}
return manager;
}
}
package notusingmode;
public class Client {
public static void main(String[] args) {
//现在没有配置文件,直接使用默认的配置,三层都生成,也就是说客户必须对这些模块都了解,才能使用它们,
//而且如果这些模块有一个发生变化,客户端也要随着改变。---------》外观模式
new Presetation().generate();
new Business().generate();
new DAO().generate();
}
}
界面和接口
界面:这里提到的并非GUI界面,而是从一个组件外部来看这个组件,能看到什么,也就是这个组件的界面,所说的外观如一个类的外部看,类的public方法就是类的外观。从一个模块外部看,模块对外提供的接口就是模块的外观。
接口:这里并非特指java中的interface,主要指的是外部和内部交互的通道,通常指一些方法。对于提出的问题,只需给客户定义一个简单接口,客户只需调用接口,其他事情交给外观来做。
Facade就是定义系统的多个模块对外的高级接口,通常需要调用内部多个模块。
模块:是真正实现功能的,各个模块之间可能有交互,但请注意各个模块不知道facade,Facade知道各个模块。
外观模式实现:A,B,C模块,模块的实现和接口,以及Facade的定义
package facade;
public interface AModuleApi {
public void testA();
}
package facade;
public class AModuleImpl implements AModuleApi {
@Override
public void testA() {
System.out.println("在A模块操作testA方法");
}
}
B,C的接口和实现类似,
package facade;
/*
* 外观对象
*/
public class Facade {
public void test(){
//在内部实现的时候,可能会调用到内部的多个模块
AModuleApi a = new AModuleImpl();
a.testA();
BModuleApi b = new BModuleImpl();
b.testB();
CModuleApi c = new CModuleImpl();
c.testC();
}
}
package facade;
public class Client {
public static void main(String[] args) {
new Facade().test(); //客户端只需和外观打交道,无需知道各个模块,由外观调用各个模块
}
}
使用外观模式解决三层的实现问题:
只需要增加一个外观对象:
package facadeSolve;
/*
* 外观对象
*/
public class Facade {
public void generate(){
//在内部实现的时候,可能会调用到内部的多个模块
Presetation p = new Presetation();
p.generate();
Business b = new Business();
b.generate();
DAO dao = new DAO();
dao.generate();
}
}
客户端通过调用new Facade().generate(); 即可
外观模式的目的是让外部更加简便地使用子系统功能。外观模式是包装已经实现的功能,来满足客户需求,而不是添加新的实现。
Facade是处于系统这边的,它组合了系统模块 的功能,对外提供一个统一接口,这样还能实现功能的共享,但有时也可以绕过外观,即不使用外观,而直接调用系统中的模块。
1,facade实现:对于一个子系统而言,外观类不需要很多,通常可以实现成一个单例,即保证只有一个外观实例。也可以直接把外观的方法写成static的,这种实现相当于将
外观类当成一个辅助工具类实现。
2,可以实现为interface,通常facade直接实现称为类,但也可以把facade实现成为真正的interface,这样会增加系统复杂性,因为这样会需要一个facade的实现,还需要
一个来获取facade接口对象的工厂。外观对象为用户提供了一个简单的、缺省的实现。
Facade的优缺点:
松散耦合(松散了客户端与子系统的耦合关系,让子系统内部的模块更容易扩展和维护)
简单易用(外观类为客户端使用子系统提供了一站式服务)
更好地划分访问的层次(有些方法系统内部使用,有些供外部使用,把需要暴露给外部的功能集中到外观众,既方便客户端使用,也很好地隐藏了内部细节)
但过多的facade使人感到迷惑,到底调用facade好呢,还是直接调用模块好。
本质:封装交互,简化调用
分享到:
相关推荐
外观模式(Facade Pattern)是设计模式中的一种结构型模式,主要目的是为了解决复杂的系统接口问题,提供一个简单的统一入口,使得客户端可以更方便地使用系统。在Java中,外观模式通常用来隐藏系统的复杂性,对外只...
### 外观模式 (Facade Pattern) #### 概述 外观模式是一种重要的设计模式,属于结构型模式之一。其核心在于通过引入一个简单的接口来隐藏一个系统中存在的复杂性,从而简化了客户端对该系统的使用。该模式的主要...
【外观模式(Facade)详解】 外观模式是一种结构型设计模式,其主要目的是为了解决复杂的系统划分成多个子系统后,如何降低子系统间的耦合度,提高系统的可维护性和可扩展性。它通过提供一个统一的接口,使得外部...
**外观模式(Facade Pattern)**是一种结构型设计模式,它主要解决的是复杂系统或子系统对外暴露一个简单统一的接口,使得客户端无需关心内部复杂的交互细节。这种模式在实际开发中广泛应用,尤其在大型项目中,它能...
外观模式(Facade Pattern)是一种结构型设计模式,用于为复杂子系统提供一个简单的接口。它通过封装系统内部的复杂性,提供一个统一的接口,使得客户端能够更加方便地使用子系统的功能。这种模式通常用于简化代码、...
设计模式面面观(13):外观模式(Facade Pattern)-结构型模式 http://blog.csdn.net/fanweiwei/archive/2008/04/17/2299641.aspx
外观模式(Facade Pattern)是设计模式中的一种结构型模式,其主要目的是为了简化客户端与复杂系统之间的交互。在C#编程中,外观模式通常用于减少客户端对子系统组件的依赖,提供一个统一的、高层次的接口,使得...
在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要... 这是第11节:结构型模式Facade外观模式
外观模式(Facade Pattern)是一种结构型设计模式,它为子系统中的一组接口提供一个统一的接口,使得子系统更容易使用。外观模式定义了一个高层接口,使得这一子系统更加容易使用。 压缩包文件代码是一个简单的 ...
外观模式是一种结构型设计模式,它的主要目标是提供一个统一的接口,用来简化对复杂系统的访问。在Java中,当你有一个复杂的子系统,而你希望客户端代码能够以一种更简洁、更易于理解的方式来与之交互时,就可以使用...
**外观模式(Facade)**是一种结构型设计模式,它的主要目的是为了解耦复杂的系统,提供一个简单的接口,使得客户端可以更方便地使用系统的子系统。在C++编程中,外观模式的应用尤为常见,因为它能够有效地降低系统...
**外观模式(Facade Pattern)**是面向对象设计模式中的一种结构型模式,它提供了一个统一的接口,用于访问子系统中的各个部分。在C#编程中,外观模式可以帮助我们简化复杂的系统接口,使得客户端代码与复杂的内部...
外观模式是一种对象结构型模式,它为子系统中的一组接口提供一个统一的高层接口,使得子系统更加容易使用。以下是外观模式的一些关键点: 简化接口:外观模式通过提供一个统一的接口来简化外部与子系统的通信,这样...
在C++中,外观模式(Facade Pattern)同样用于为子系统中的一组接口提供一个统一的接口,使得子系统更容易使用。压缩包文件代码是一个简单的C++实现外观模式的示例。 1、定义各个子系统的类及其接口。 2、定义外观类...
C#面向对象设计模式纵横谈\C#面向对象设计模式纵横谈\10.Facade 外观模式(结构型模式).wmv )
**外观模式(Facade)**是软件工程中一种常用的设计模式,它为复杂的系统或子系统提供了一个统一的入口点,简化了客户端与复杂系统之间的交互。这种模式将客户端与子系统的内部实现细节隔离开来,使得客户端只需要...