一、概述
引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口。简而言之,外观模式就是定义了一个高层接口,这个接口可以使得这一子系统更加容易使用。
如果没有这个外观类,那么每个客户类需要和多个子系统之间进行复杂的交互,系统的耦合将很大,而当引入了外观类之后,客户类只需与外观类进行交互,客户类与子系统之间原有的复杂引用关系由外观类来实现,降低了系统的耦合度。
外观模式又称为门面模式,是迪米特法则的一种具体实现。
二、结构与实现
- 结构
(1)Facade类:
客户端调用它的方法,在外观角色可以知道相关的子系统的功能和职责,在正常情况下,它将所有从客户端发来的请求委派到相应的子系统,传递给相应的子系统对象操作。
(2)SubSystem类:
处理从外观类传过来的请求,子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另一个客户端而已。
- 实现
class SubSystemA{
public void f1(){
//具体业务实现
}
}
class SubSystemB{
public void f2(){
//具体业务实现
}
}
class SubSystemC{
public void f3(){
//具体业务实现
}
}
//外观角色
class Facade{
private SubSystemA a=new SubSystemA();
private SubSystemB b=new SubSystemB();
private SubSystemC c=new SubSystemC();
public void f(){
a.f1();
b.f2();
c.f3();
}
}
public class Client{
public static void main(String args[]){
Facade facade=new Facade();
facade.f();
}
}
三、应用案例
- 分析:三个操作,读取文件(FileReader),加密文件(CipherMachine),保存加密文件(FileWriter)可以看做是三个子系统类。这三个操作将会被外观角色(Facade)所集中。
- 类图:
- 代码实现:
//三个子系统
class CipherMachine {
public String encrypt(String text){
System.out.println("数据加密ing...");
//具体略
}
}
class FileReader {
public String read(String fileNameSrc){
System.out.println("读取文件,获取明文:");
//具体略
}
}
class FileWriter {
public void write(String encryptStr,String fileName){
System.out.println("保存密文,导入文件...");
//具体略
}
}
//外观角色
class Facade {
private FileReader fileReader;
private CipherMachine cipherMachine;
private FileWriter fileWriter;
public Facade(){
fileReader=new FileReader();
cipherMachine=new CipherMachine();
fileWriter=new FileWriter();
}
public void fileOpe(String fileNameSrc,String fileNameDes){
String read = fileReader.read(fileNameSrc);
String encrypt = cipherMachine.encrypt(read);
fileWriter.write(encrypt,fileNameDes);
}
}
//客户端
public class Client {
public static void main(String[] args) {
Facade facade=new Facade();
facade.fileOpe("src//1.txt","src//2.txt");
}
}
四、抽象外观类
在标准的外观模式中,如果需要增加或删除、更换子系统类,必须修改外观模式类或客户端的源代码,这违背了开闭原则。因此通过引入抽象外观类对系统进行改进,在一定程度上可以解决该问题。
引入抽象外观类,客户端直接与抽象外观类进行交互,就无需修改客户端的源代码,对于新的业务需求,不需要修改原有外观类,对应增加一个新的具体外观类即可。
如应用案例:引入抽象外观类AbstractFacade。客户端将facade声明提升到AbstractFacade。此时,不论是引入新的子系统,还是引入新的外观类,都很好地遵循了开闭原则。
五、总结
(1)为子系统中地一组接口提供一个统一的接口。又称门面模式,迪米特法则的具体实现。
(2)适用:当要为访问一系列复杂子系统提供一个简单入口时;当客户端与多个子系统之间存在很大的依赖性;在层次化结构中可以使用外观模式定义系统中的每一层的入口,层与层之间不直接产生联系,而要通过外观类建立联系,降低层之间的耦合度。