在现实生活中,常常存在办事较复杂的例子,如办房产证或注册一家公司,有时要同多个部门联系,这时要是有一个综合部门(政务窗口 )能解决一切手续问题就好了。
软件设计也是这样,当一个系统的功能越来越强,子系统会越来越多,客户对系统的访问也变得越来越复杂。这时如果系统内部发生改变,客户端也要跟着改变,这违背了“开闭原则”,也违背了“迪米特法则”,所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观模式的目标。
外观(Facade)模式/门面模式 的结构比较简单,主要是定义了一个高层接口。它包含了对各个子系统的引用,客户端可以通过它访问各个子系统的功能。现在来分析其基本结构和实现方法。
模式的结构
外观(Facade)模式包含以下主要角色。
- 外观(Facade)角色:为多个子系统对外提供一个共同的接口。
- 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
- 客户(Client)角色:通过一个外观角色访问各个子系统的功能。
文件保存类, 充当子类系统类
public class FileWriter {
public void write(String encryptStr, String path) {
try (FileOutputStream fileOutputStream = new FileOutputStream(path)) {
fileOutputStream.write(encryptStr.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件读取类, 充当子系统类
public class FileReader {
public String read(String path) {
StringBuilder stringBuffer = new StringBuilder();
try (FileInputStream fileInputStream = new FileInputStream(path)) {
int data = 0;
while ((data = fileInputStream.read()) != -1) {
stringBuffer.append((char) data); //char
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuffer.toString();
}
}
加密外观类, 充当外观类
public class EncryptFacade {
//维持对子系统对象的引用
private FileReader fileReader;
private CipherMachine cipherMachine;
private FileWriter fileWriter;
public EncryptFacade() {
fileReader = new FileReader();
cipherMachine = new CipherMachine();
fileWriter = new FileWriter();
}
//对外提供的门面方法, 调用子系统对象的业务方法
public void fileEncrypt(String fromPath, String toPath) {
String text = fileReader.read(fromPath);
System.out.println(">>>>>>>>>> : 读取文件[ " + fromPath + " ]中的明文数据 : " + text);
String encryptStr = cipherMachine.encrypt(text);
System.out.println(">>>>>>>>>> : 明文数据加密后的结果 : " + encryptStr);
fileWriter.write(encryptStr, toPath);
}
}
数据加密类(求模运算), 充当子系统类
public class CipherMachine {
public String encrypt(String text) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
String s = String.valueOf(text.charAt(i) % 7);
result.append(s);
}
return result.toString();
}
}
客户端测试类
public class ClientTest {
/**
* 下面是一个使用外观设计模式的简单示例程序 : 写一个用于文件加密的模块,该模块的功能为对指定文件中的数据进行加密并将加密之后的数据保存到新的文件中.
* 具体流程包括三个部分 : 读取源文件中的数据, 数据加密, 将加密后的数据写入到新文件
*/
private static final String FROM_PATH = "Picture\\from.txt";
private static final String TO_PATH = "Picture\\to.txt";
public static void main(String[] args) {
//只要调用门面类的方法就能完成文件内容读取, 加密的操作了,调用比一个方法一个方法的调用要简单。
EncryptFacade encryptFacade = new EncryptFacade();
encryptFacade.fileEncrypt(FROM_PATH, TO_PATH);
}
}