创建型模式之 外观模式
前言
外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便。
模式定义
外观模式(FacadePattern)为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式又称为门面模式,它是一种对象结构型模式。外观模式是迪米特法则的一种具体实现,通过引入一个新的外观角色可以降低原有系统的复杂度,同时降低客户类与子系统的耦合度。
模式结构
Facade(外观角色):在客户端可以调用它的方法,在外观角色中可以知道相关的(一个或者多个)子系统的功能和责任;在正常情况下,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理。
SubSystem(子系统角色):在软件系统中可以有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能;每一个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观类传过来的请求;子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。
UML类图
适用场景
在以下情况下可以使用外观模式:
当要为访问一系列复杂的子系统提供一个简单入口时可以使用外观模式。
客户端程序与多个子系统之间存在很大的依赖性。引入外观类可以将子系统与客户端解耦,从而提高子系统的独立性和可移植性。
在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。
看看大神怎么用
外观模式并不给系统增加任何新功能,它仅仅是简化调用接口。在几乎所有的软件中都能够找到外观模式的应用,如绝大多数B/S系统都有一个首页或者导航页面,大部分C/S系统都提供了菜单或者工具栏,在这里,首页和导航页面就是B/S系统的外观角色,而菜单和工具栏就是C/S系统的外观角色,通过它们用户可以快速访问子系统,降低了系统的复杂程度。所有涉及到与多个业务对象交互的场景都可以考虑使用外观模式进行重构。
高清有码
前戏:去茶楼喝茶,你不必关心茶叶、茶具以及水的任何事情,只用拿着杯子喝就行了。
Demo角色介绍:
Client: 客户端 用来调用
AbstractFacade
/**
* 抽象外观角色
* Created by R on 2016/8/21.
*/
public abstract class AbstractFacade {
abstract void getTea();
}
FacadeA
/**
* 外观角色 A
* Created by R on 2016/8/21.
*/
public class FacadeA extends AbstractFacade{
@Override
void getTea() {
SubSystemA water = new SubSystemA();
SubSystemB leaf = new SubSystemB();
new SubSystemC().MakeTea(water , leaf);
}
}
FacadeB
/**
* 外观角色 A
* Created by R on 2016/8/21.
*/
public class FacadeB extends AbstractFacade{
@Override
void getTea() {
SubSystemA water = new SubSystemA();
SubSystemB leaf = new SubSystemB();
new SubSystemC().MakeTea(water , leaf);
System.out.println("倒掉第一泡,将第二泡倒入茶杯");
}
}
SubSystemA
/**
* 子系统A
* Created by R on 2016/8/21.
*/
public class SubSystemA {
public String getWater(){
return "90℃热水";
}
}
SubSystemB
/**
* 子系统B
* Created by R on 2016/8/21.
*/
public class SubSystemB {
public String getLeaf(){
return "铁观音";
}
}
SubSystemC
/**
* 子系统C
* Created by R on 2016/8/21.
*/
public class SubSystemC {
public void MakeTea(SubSystemA water, SubSystemB tea_leaf){
System.out.println("将" + tea_leaf.getLeaf() + "和" + water.getWater() + "倒入紫砂壶");
}
}
ConfigFile
/**
* 假装他是配置文件
* Created by R on 2016/8/21.
*/
public class ConfigFile {
public static final Class<? extends AbstractFacade> facade = FacadeA.class;
public static AbstractFacade getFacade() {
try {
return facade.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return new FacadeA();
}
}
Client
/**
* 外观模式
* Created by R on 2016/8/21.
*/
public class Client {
public void main(){
AbstractFacade facade = ConfigFile.getFacade();
facade.getTea();
}
}
输出:
配置文件中为 SubSystemA:
配置文件中为 SubSystemB:
总结
外观模式比较简单,解决的问题也比较简单,就是将复杂化的调用关系封装到一个类中,在客户端只需要对这个外观类进行操作,而为了能更符合开闭原则,可以对其进行优化,定义一个外观抽象类,再使客户端通过一个固定的方式拿到可随时改变的实体,这样既实现了调用关系的抽离,又遵循了开闭原则。
就是为了让客户端衣来张口饭来伸手。