什么是外观模式
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
外观模式遵循迪米特法则:
- 一个软件实体应当尽可能少的与其他实体发生相互作用。
外观模式的核心:
- 为子系统提供统一的接口。封装子系统的复杂性,便于客户端调用。
结构
Facade类:
- 这个外观类为子系统提供一个共同的对外接口。
Clients:
- 客户对象通过一个外观接口读写子系统中各个接口的数据资源。
适用场景
在以下情况下可以考虑使用外观模式:
- 设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观模式。
- 开发阶段,子系统越来越复杂,增加外观模式提供一个简单的调用接口。
- 维护一个大型遗留系统的时候,可能这个系统已经非常难以维护和扩展,但又包含非常重要的功能,为其开发一个外观类,以便新系统与其交互。
优点
- 实现了子系统与客户端之间的松耦合关系。
- 客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易。
开发中常见的场景
- JDBC封装后的,Commons提供的DBUtils类;Hibernate提供的工具类;Spring JDBC工具类等。
举例
下面以公司注册为例说明,没有外观类时公司注册的每个环节客户端都要亲力亲为,有了外观类后,这些事情交给外观类来完成。
类图
未使用外观模式
使用外观模式
代码
外观类
package com.match.facade;
/**
* 办理注册公司流程的外观类
* @author Match
*
*/
public class RegisterFacade
{
public void register()
{
ICB a = new ShangHaiICB();
QIB b = new ShangHaiQIB();
TaxBureau c = new ShangHaiTaxBureau();
Bank d = new ICBCBank();
a.checkName();
b.orgCodeCertificate();
c.taxCertificate();
d.openAccount();
}
}
子系统类
package com.match.facade;
/**
* 工商局
* @author Match
*
*/
public interface ICB
{
/**
* 核名
*/
void checkName();
}
/**
* 上海工商局
* @author Match
*
*/
public class ShangHaiICB implements ICB
{
@Override
public void checkName()
{
System.out.println("在上海工商局检查名字是否有冲突。");
}
}
package com.match.facade;
/**
* 质检局
* @author Match
*
*/
public interface QIB
{
/**
* 办理组织机构代码证
*/
void orgCodeCertificate();
}
/**
* 上海质检局
* @author Match
*
*/
public class ShangHaiQIB implements QIB
{
@Override
public void orgCodeCertificate()
{
System.out.println("在上海质检局办理组织机构代码证。");
}
}
package com.match.facade;
/**
* 税务局
* @author Match
*
*/
public interface TaxBureau
{
/**
* 办理税务登记证
*/
void taxCertificate();
}
/**
* 上海税务局
* @author Match
*
*/
public class ShangHaiTaxBureau implements TaxBureau
{
@Override
public void taxCertificate()
{
System.out.println("在上海税务局办理税务登记证。");
}
}
package com.match.facade;
/**
* 银行
* @author Match
*
*/
public interface Bank
{
/**
* 开户
*/
void openAccount();
}
/**
* 中国工商银行
* @author Match
*
*/
public class ICBCBank implements Bank
{
@Override
public void openAccount()
{
System.out.println("在中国工商银行开户。");
}
}
客户端类
package com.match.facade;
/**
* 客户端类
* @author Match
*
*/
public class Client
{
public static void main(String[] args)
{
new RegisterFacade().register();
}
}
测试输出
在上海工商局检查名字是否有冲突。
在上海质检局办理组织机构代码证。
在上海税务局办理税务登记证。
在中国工商银行开户。