外观模式 Facade
先做个总结:
外观模式就是提供一个高层接口来集成、制定、调用子系统的功能,达到客户端和子系统之间的解耦
两篇文章来解释:
一、
外观模式(又称门面模式)是软件工程中常用的一种软件设计模式。它为子系统中的一组接口提供一个统一的高层接口。使用子系统更容易使用。
?
结构Facade
这个外观类为子系统中Packages 1、2、3提供一个共同的对外接口
Clients
客户对象通过一个外观接口读写子系统中各接口的数据资源。
Packages
客户可以通过外观接口读取的内部库。
?
?
示例Java
这是一个抽象的示例。一个客户“you”通过外观接口“computer”获取计算机内部复杂的系统信息。
/* Complex parts */
class CPU {
public void freeze() { ... }
public void jump(long position) { ... }
public void execute() { ... }
}
?
class Memory {
public void load(long position, byte[] data) {
...
}
}
?
class HardDrive {
public byte[] read(long lba, int size) {
...
}
}
?
/* Façade */
class Computer {
public void startComputer() {
cpu.freeze();
memory.load(BOOT_ADDRESS, hardDrive.read(BOOT_SECTOR, SECTOR_SIZE));
cpu.jump(BOOT_ADDRESS);
cpu.execute();
}
}
?
/* Client */
class You {
public static void main(String[] args) {
Computer facade = new Computer();
facade.startComputer();
}
}
?
注意和其他设计模式的区别
?
代理模式
1 代理模式中的原类和代理类继承同一父类;
2 原类对象与代理类对象接口相同,功能一致;
3 起到了隐藏原类的作用。
适配器模式
1 只有适配器继承目标接口;
2 将原有类接口转换为目标代码需求的接口。
外观模式
是多个类的集成、统一适配。
?
?
二、
外观模式属于结构型模式,其意图是为子系统中的一组接口提供一个一致的界面,Fa?ade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。在项目设计中,把一个系统划分成为若干个子系统由利于降低系统的复杂性,一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小,达到该目标的途径之一就是引入一个外观对象,它为子系统中较一般的设施提供了一个单一而简单的界面。
????? 实用性:l???????? 当需要为一个复杂子系统提供一个简单的接口时。子系统往往因为不断演化而变得越来越复杂,大多是模式使用时都会产生更多更小的类,这使得子系统更具有可重用性,也更容易对子系统进行订制,但是这也给那些不需要订制子系统的用户带来一些使用上的困难。l???????? 客户程序与抽象类的实现部分之间存在很大的依赖性,引入fa?ade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。l???????? 当你需要构建一个层次结构的子系统时,使用Fa?ade模式定义子系统中每层的入口点,如果子系统间是相互依赖的,你可以让他们通过Facade进行通讯,从而简化他们之间的依赖关系。例如在一个泡茶的过程中,需要作如下的工作:烧开水,准备茶叶,把茶叶放在被子里,把烧开的水放到茶杯中,只有经过这些过程之后才能泡出好的茶叶来。这是一个常用的步骤,80%的泡茶步骤都是这个样子的,可以把这些动作串联起来,形成一个整体的步骤,就是MakeACuppa(),这样在调用步方法时也比较方便。这便是外观模式,里面的细节被屏蔽掉了。当然如果想更详细的控制每个步骤地过程,也允许进行相应的控制,但是必须自己创建类。
图1参与者:????? Fa?ade(DacadeCuppaMaker):知道那些子系统类负责处理请求;将客户的请求代理给适当的子系统。????? SubSystem classes(water,Teabag):实现自系统的功能,处理由Fa?ade 对象指派的任务,没有Facade的任何相关信息,即没有指向Fa?ade的指针。他们之间的协作关系是:客户程序通过发送请求给Fa?ade的方式与子系统通讯,Facade将这些消息转发给适当的子系统对象,尽管是子系统的有关对象在做实际工作,但Fa?ade模式本身也必须将它的接口转换成子系统的接口。使用fa?ade的客户程序不需要直接访问子系统对象。????? 使用Fa?ade模式有下面一些优点:1.?????? 他对客户屏蔽子系统组件,因而减少了客户处理的对象的树木并使得子系统使用起来更加方便。2.?????? 实现了自系统与客户之间的松散耦合关系,而自系统内部的功能组件往往是紧耦合的。松耦合关系使得自系统的组件变化不会影响到他的客户。3.?????? 如果需要他们不限制他们使用子系统类。在本系统中,Teacup使用water和TeaBag泡一杯茶水,泡茶的过程比较复杂,这相当于一个子系统,在这个子系统中泡茶的每一个步骤都是紧密相连的,如果使用每个子类按照泡茶的步骤一步步地走下来也可以达到目的,但是在这个过程中需要创建子类,调用子类的方法,或者检测子类的变量,而在客户端大部分的操作都是使用一样的代码,把这些一样的代码抽取出来形成一个能完成一特定功能的类,便形成了Fa?ade模式的代码。使用了Fa?ade模式就使得这些操作聚合在一起,方便客户端调用。相应的代码:Water代码:package facade;public class Water{??? boolean waterIsBoiling;??? public Water(){?????? setWaterIsBoiling(false);?????? System.out.println("纯净的水准备好了");??? }??? public void setWaterIsBoiling(boolean isWaterBoiling){?????? waterIsBoiling = isWaterBoiling;??? }??? public boolean getWaterIsBoiling(){?????? return waterIsBoiling;??? }??? public void boilFacadeWater(){?????? setWaterIsBoiling(true);?????? System.out.println("水在沸腾");??? }}TeaBag代码:package facade;public class TeaBag{??? public TeaBag(){?????? System.out.println("清香的茶包准备好了!");??? }}TeaCup代码:package facade;public class TeaCup{??? private boolean teaBagIsSteeped;??? private Water facadeWater;??? private TeaBag facadeTeaBag;??? public TeaCup(){?????? setTeaBagIsSteeped(true);?????? System.out.println("茶杯准备好了");??? }??? public void setTeaBagIsSteeped(boolean isTeaBagSteeped){?????? teaBagIsSteeped = true;??? }??? public boolean getTeaBagIsSteeped(){?????? return teaBagIsSteeped;??? }??? public void addFacadeTeaBag(TeaBag facadeTeaBagIn){?????? facadeTeaBag = facadeTeaBagIn;?????? System.out.println("茶包放在茶杯了");??? }??? public void addFacadeWater(Water facadeWaterIn){?????? facadeWater = facadeWaterIn;??? }??? public void steepTeaBag(){?????? if(facadeTeaBag != null &&facadeWater != null && facadeWater.getWaterIsBoiling()){?????? System.out.println("茶叶渗透到杯子中了");?????? setTeaBagIsSteeped(true);?????? }?????? else{?????????? System.out.println("茶叶没有渗透到杯子中");?????????? setTeaBagIsSteeped(false);?????? }??? }??? public String toString(){?????? if(getTeaBagIsSteeped()){?????????? return "一杯又香又浓的茶冲好了";?????? }?????? else?????????? return "一杯又香又浓的茶冲好了";??? }}FacadeCuppaMaker代码;package facade;public class FacadeCuppaMaker{??? private boolean TeaBagIsSteeped;??? public FacadeCuppaMaker(){?????? System.out.println("FacadeCuppaMaker 准备好冲茶了");??? }??? public TeaCup makeACuppa(){?????? TeaCup cup = new TeaCup();?????? TeaBag teaBag= new TeaBag();?????? Water water = new Water();?????? cup.addFacadeTeaBag(teaBag);?????? water.boilFacadeWater();?????? cup.addFacadeWater(water);?????? cup.steepTeaBag();?????? return cup;??? }}Client代码:package facade;public class Client{??? public static void main(String[] args){?????? FacadeCuppaMaker cuppaMaker = new FacadeCuppaMaker();?????? TeaCup teaCup = cuppaMaker.makeACuppa();?????? System.out.println(teaCup);??? }}总结:外观模式的主要用途就是为子系统的复杂处理过程提供方便的调用方法,使得子系统更加容易被使用。Fa?ade对象通常属于Singleton模式。?