外观模式的引文叫Facade模式,说实话,对于这个模式把Facade翻译成“外观”不大贴切,我觉得翻译成“门面”、“表面”更加好。
首先引入外观模式的情景------------>我们在实践中会遇到这样的情景:客户程序需要使用多个子系统,并且多数情况下需要这些子系统相互配合来完成一个特定的功能。最简单的实现就是客户端程序直接操作这些子系统,通过以一定逻辑调用这些子系统的来完成任务。但是,如果遇到需要通过不同的子模块组合完成不同功能的情况,使用上述策略就不太合适了,因为这样会造成①客户端程序过于臃肿,②需要管理过多子系统成员、③逻辑过于复杂、④当子系统发生变化时,客户端的程序代码更改就十分麻烦。
于是,我们使用外观模式模式来解决这个问题,引入外观类。
一图胜千言,先上图!
Client-------------------------->客户类
Facade------------------------->外观类(外观模式精髓)
SubSystem*------------------>子系统类
通过类图可以看出,用户不是直接与子系统发生关联,而是与Facade类直接关联,Facade关联多个子系统。
这样做的好处是:①降低了客户类与子系统类之间的耦合度②客户类直接操作外观类,而无需关心子系统的实现③子系统修改是,只需要修改使用它的Facade类的代码即可。
在网上有一句话说的特别好,与大家分享:在层次化结构中,可以使用 Facade 模式定义系统中每一层的入口。这句话的意思就是说,每一个层次的入口都用一个外观类管理,来负责与上一层次的系统模块进行交互。这大大提高了系统的简洁性。
最后,我们来看一段代码。
public 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 fileNameS,String fileNameD)
{
String plainStr=reader.read(fileNameS);
String encryptStr=cipher.encrypt(plainStr);
writer.write(encryptStr, fileNameD);
}
}
class FileReader//读文件类
{
public String read(String fileName)
{
System.out.println("读取文件,获取明文");
StringBuffer sb=new StringBuffer();
try
{
FileInputStream inFS=new FileInputStream(fileName);
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();
}
}
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;
}
}
class FileWriter//保存文件类
{
public void write(String encryptStr,String fileName)
{
System.out.println("保存密文,写入文件");
try{
FileOutputStream outFS=new FileOutputStream(fileName);
outFS.write(encryptStr.getBytes());
outFS.close();
}
catch(FileNotFoundException e)
{
System.out.println("文件不存在");
}
catch(IOException e)
{
System.out.println("文件操作错误");
}
}
}
class Client
{
public static void main(String args[])
{
EncryptFacade ef=new EncryptFacade();
ef.fileEncrypt("a.txt", "b.txt");
}
}
注释中已经标明外观类,Client是客户类,其余的都是子系统类。
剖析代码,可以看到是否使用外观模式对于实现逻辑的总代码量是相同的。但是,使用外观模式用户类所获得的便利性与简洁性是不言而喻的。所以说,外观模式主要是为客户服务的!