设计模式学习(七)——外观模式

外观模式定义

外观模式(Facade Pattern)提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

外观模式允许我们让客户和子系统之间避免紧耦合,它遵守“最少知识”原则。这个原则希望我们在设计中,不要让太多的类耦合在一起,免得修改系统中一部分,会影响到其他部分。如果许多类之间相互依赖,那么这个系统就会变成一个易碎的系统,它需要花许多成本维护,也会因为太复杂而不容易被其他人了解。

外观模式对客户屏蔽子系统组件,减少了客户处理的对象数目,使得子系统使用起来更加容易。


外观模式结构图

图中:

  • Facade表示外观角色,客户端可以调用这个方法,此角色知道相关的(一个或多个)子系统的功能和责任,在正常情况下,将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理;

  • Subsystem表示子系统角色,一个系统可以同时有一个或多个子系统,每一个子系统都不是一个单独的类,而是一个类的集合,它实现子系统的功能,每一个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观类传过来的任务,子系统并不知道外观的存在,对于子系统而言,外观仅仅是另外一个客户端而已。


外观模式实例——文件加密

实例说明

某系统需要提供一个文件加密模块,加密流程包括三个操作,分别是读取源文件、加密、保存加密之后的文件。读取文件和保存文件使用流来实现,这三个操作相对独立,其业务代码封装在三个不同的类中。现在需要提供一个统一的加密外观类,用户可以直接使用该加密外观类完成文件的读取、加密和保存三个操作,而不需要与每一个类进行交互,使用外观模式设计该加密模块,要求编程模拟实现。

实例类图

实例类图中与外观模式结构图对应的类主要有:

  • EncryptFacade充当外观类;

  • FileReader、CipherMachine和FileWriter充当子系统类。

实例代码

EncryptFacade.java:

//加密外观类:外观类
class EncryptFacade
{
private FileReader reader;
private CipherMachine cipher;
private FileWriter writer;

public EncryptFacade()
{
reader = new FileReader();
cipher = new CipherMachine();
writer = new FileWriter();
}

public void fileEncrypt(String fileNameSrc, String fileNameDes)
{
String plainStr = reader.read(fileNameSrc);
String encryptStr = cipher.encrypt(plainStr);
writer.write(encryptStr,fileNameDes);
}
}

FileReader.java:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

//文件读取类:子系统类
class FileReader
{
public String read(String fileNameSrc)
{
System.out.println("读取文件,获取明文。");
StringBuffer sb = new StringBuffer();
try{
FileInputStream inFS=new FileInputStream(fileNameSrc);
int data;
while((data=inFS.read())!=-1)
{
sb = sb.append((char)data);
}
inFS.close();
}
catch(FileNotFoundException e)
{
System.out.println("文件不存在!");
}
catch(IOException e)
{
System.out.println("文件操作错误!");
}
return sb.toString();
}
}

CipherMachine.java:

//数据加密类:子系统类
class CipherMachine
{

public String encrypt(String plainText)
{
System.out.println("数据加密,将明文转换为密文。");
String es="";
for(int i=0;i<plainText.length();i++)
{
String c=String.valueOf(plainText.charAt(i)%7);
es+=c;
}
return es;
}
}

FileWriter.java:

import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

//文件保存类:子系统类
class FileWriter
{
public void write(String encryptStr,String fileNameDes)
{
System.out.println("保存密文,写入文件。");
try{
FileOutputStream outFS = new FileOutputStream(fileNameDes);
outFS.write(encryptStr.getBytes());
outFS.close();
}
catch(FileNotFoundException e)
{
System.out.println("文件不存在!");
}
catch(IOException e)
{
System.out.println("文件操作错误!");
}
}
}

Client.java:

//客户端测试类
class Client
{
public static void main(String args[])
{

EncryptFacade ef = new EncryptFacade();
ef.fileEncrypt("src/src.txt","src/des.txt");
}
}

运行结果

Console输出:

src.txt和des.txt文件中的内容为:

附加描述

在本实例中,对src文件夹下的文件src.txt中的数据进行加密,该文件的内容为“Hello world!”,加密之后将密文保存到src文件夹下的另一个文件des.txt中,程序运行后保存在文件中的密文为“233364062325”。在加密类CipherMachine中,采用求模运算对明文进行加密,将明文中的每一个字符除以一个整数(本例中为7,可以由用户自行设置)后取余数作为密文。


后话

Facade模式的思想简单,但是用处甚广。