简介:《设计模式》对外观模式的定义:为子系统中的一组接口提供一个统一接口,外观模式定义了一个更高层的接口,使子系统更加容易使用。也就是说:外观模式隐藏了系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
外观模式结构图:

角色:
1:门面角色(Facade):外观模式的核心,被客户角色所调用,它熟悉子系统的功能
2:子系统角色:实现了子系统的功能,它对客户角色和Facade角色是未知的。
3:客户角色(Client):通过调用Facade来完成要实现的功能
代码实操:
假设一台电脑,它包含了 CPU(处理器),Memory(内存) ,Disk(硬盘)这几个部件,若想要启动电脑,则先后必须启动 CPU、Memory、Disk。关闭也是如此。但是实际上我们在电脑开/关机时根本不需要去操作这些组件,因为电脑已经帮我们都处理好了,并隐藏了这些东西。

CPU类(子系统中的):
public class CPU {
public void startup(){
System.out.println("cpu startup");
}
public void shutdown(){
System.out.println("cpu shutdown");
}
}
Memory 类(子系统中的):
public class Memory {
public void startup(){
System.out.println("Memory startup");
}
public void shutdown(){
System.out.println("Memory shutdown");
}
}
Disk 类(子系统中的):
public class Disk {
public void startup(){
System.out.println("Disk startup");
}
public void shutdown(){
System.out.println("Disk shutdown");
}
}
Computer 类(即Facade类):
public class Computer {
private CPU cpu;
private Memory memory;
private Disk disk;
public Computer(){
cpu = new CPU();
memory = new Memory();
disk = new Disk();
}
public void startup(){
System.out.println("start the computer");
cpu.startup();
memory.startup();
disk.startup();
System.out.println("start computer finished");
}
public void shutdown(){
System.out.println("begin to close the computer");
cpu.shutdown();
memory.shutdown();
disk.shutdown();
System.out.println("computer closed");
}
}
User类(Client类):
public class User {
public static void main(String[] args) {
Computer computer = new Computer();
computer.startup();
computer.shutdown();
}
}
运行结果:

从这个例子来看,Client并不需要知道子系统内部的具体实现,只需要和Facade进行交互就可以了;如果没有Facade的话,客户端需要以此与子系统中的三个类进行交互。
优点:
1:外观模式对客户端屏蔽了子系统组件,从而简化了接口,减少了客户端处理的对象数目并使子系统的使用 更加简单。
2:外观模式实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件是紧耦合的。松耦合使子系统的组件变化不会影响 到它的客户端。
缺点:
增加新的子系统可能需要修改外观类或客户端,违背了“开闭原则”
应用场景:
1.想要为一个复杂的子系统提供一个简单接口。子系统随着其自身的发展往往变得越来越复杂。它们应用的大多数的设计模式会导致类的数量更多,代码段更少。这使得该子系统可重用更好,也更容易进行自定义。而对于某些无法自定义的客户端来说,它也变得难以使用。门面层可以提供对大多数客户端来说足够好的简化的调用接口。只有极少数高度定制化的客户端需要直接调用门面层后的底层代码。
2.在客户端和抽象层的实现类之间存在大量的依赖关系。引入一个门面层能够将客户端的子系统与其他子系统进行解耦,从而促进子系统的独立性和可移植性。
3.想要给子系统增加层级。使用一个门面层对每个子系统级别分别定义一个入口点。如果子系统之间存在依赖关系,那么可以通过令这些子系统之间的交互全部需要经由门面层来简化彼此的依赖关系。
4.在设计初期阶段,应该有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层,业务逻辑层和表示层的层与层之间建立Facade,这样可为复杂的子系统提供一个简单的接口,使得藕合大大降低。其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也会产生很多很小的类,这本来是好事,但是也给外部调用它们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但是因为它包含重要的功能,新的需求开发必须要依赖于他。此时用外观模式Facade也是非常合适的。你可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。
外观模式使用注意事项:
- 如果想引入一个Facade层,那么并不是仅仅创建几个额外的类就能实现的。虽然分层的体系结构更好,但是需要评估每一层的不同需要。
- Facade层不能强制其他系统的行为,而是否使用Facade层应始终是可选择的。如果客户端要与底层组件直接交互,那么我们同样需要提供一个途径对Facade层进行旁路。
- 有些Facade层中的方法仅仅有一两行代码,并主要用于调用其他组件。如果Facade层是如此的简单,那么这往往起不到解耦的作用,因为客户端也可以这样直接去调用底层组件。
- 控制器不是外观模式
- 外观模式并不是一层用于保障系统安全、彻底隐藏重要数据与实现的代码层。
- 不要在一开始就创建外观模式。如果你觉得以后子系统会不断变化,并变得更复杂,提早创建Facade层会造成难以创建子类和完成接口命名,最好在系统变得复杂之后,再去创建Facade层。
- 子系统并不会意识到Facade层的存在,同样也不应在子系统内对门面层进行引用。
- 会为子系统的一组接口提供统一的对外接口
- 客户端与子系统交互需要通过Facade层发送请求,再由门面层将请求转发给合适的子系统
- 虽然子系统对象负责执行实际的工作,Facade层仍然要完成将自己的接口转换成子系统内部接口的翻译工作
- 客户端使用Facade层时不需要再去访问子系统内部对象。

1918

被折叠的 条评论
为什么被折叠?



