Java设计模式- 结构型设计模式-外观模式
从这一专栏开始将学习设计模式,上课学习和自己总结归纳的笔记将总结出来供大家参考。
参考书籍:《设计模式就该这样学》
其他文章:
文章目录
一、结构型设计模式
在GOF23种设计模式中,有三种类型的设计模式,分别是:创建型设计模式、结构型设计模式、行为型设计模式。
结构型设计模式有:代理模式、适配器模式、桥接模式、装饰模式、外观模式、享元模式、组合模式 7 种结构型模式。
类结构型模式:关心类的组合,由多个类组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。
对象结构型模式:关心类与对象的组合,通过关联关系,在一个类中定义另外一个类的实例对象,然后通过该对象调用相应的方法。
二、外观模式
1.外观模式定义
外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便。
外观模式又称为门面模式,它是一种对象结构型模式。外观模式是迪米特法则的一种具体实现,通过引入一个新的外观角色可以降低原有系统的复杂度,同时降低客户类与子系统的耦合度。
2.外观模式的角色:
Facade(外观角色):在客户端可以调用它的方法,在外观角色中可以知道相关的(一个或者多个)子系统的功能和责任;在正常情况下,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理。
SubSystem(子系统角色):在软件系统中可以有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能;每一个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观类传过来的请求;子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。
3.外观模式的特点
优点:
1.通过引入一个新的外观角色来降低原有系统的复杂度,同时降低客户类与子系统的耦合度(所指的子系统是一个广义的概念,它可以是一个类、一个功能模块、系统的一个组成部分或者一个完整的系统),使得子系统更加易用。
2.它实现了子系统与客户端之间的松耦合关系,这使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可
3.个子系统的修改对其他子系统没有任何影响,而且子系统的内部变化也不会影响到外观对象
缺点:
1.不能很好地限制客户端直接使用子系统类,如果对客户端访问子系统类做太多的限制则减少了可变性和灵活性
2.如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则
适用环境:
1.要为访问一系列复杂的子系统提供一个简单入口
2.客户端程序与多个子系统之间存在很大的依赖性
3.在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而是通过外观类建立联系,降低层之间的耦合度
4.外观模式的类图
5.外观模式的代码实现
5.1具体案例:
某软件公司要开发一个可应用于多个软件的文件加密模块,该模块可以对文件中的数据进行加密并将加密之后的数据存储在一个新文件中,具体的流程包括3个部分,分别是读取源文件、加密、保存加密之后的文件,其中,读取文件和保存文件使用流来实现,加密操作通过求模运算实现。这3个操作相对独立,为了实现代码的独立重用,让设计更符合单一职责原则,这3个操作的业务代码封装在3个不同的类中。
现使用外观模式设计该文件加密模块。
类图如下:
具体代码实现:
1.外观类EncryptFacade
/**
* 加密外观类,充当外观类
* @author WxrStart
* @create 2022-05-31 16:50
*/
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 fileNameSrc, String fileNameDes) {
String plainStr = reader.read(fileNameSrc);
String encryptStr = cipher.encrypt(plainStr);
writer.write(encryptStr, fileNameDes);
}
}
2.子系统FileReader
/**
* 文件读取子系统
* @author WxrStart
* @create 2022-05-31 16:46
*/
public class FileReader {
public String read(String fileNameSrc){
System.out.print("读取文件,获取明文:");
StringBuffer sb = new StringBuffer();
try {
FileInputStream inFS = new FileInputStream(fileNameSrc);
int data;
while((data=inFS.read())!=-1) {
sb = sb.append((char)data);
}
inFS.close();
System.out.println(sb.toString());
} catch (FileNotFoundException e) {
System.out.println("文件不存在");
}catch (IOException e) {
System.out.println("文件操作错误!");
}
return sb.toString();
}
}
3.子系统FileWriter
/**
*文件保存子系统
* @author WxrStart
* @create 2022-05-31 16:49
*/
public 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("文件操作错误!");
}
}
}
4.子系统CipherMachine
/**
* 数据加密类,充当子系统类
* @author WxrStart
* @create 2022-05-31 16:52
*/
public class CipherMachine {
public String encrypt(String plainText) {
System.out.print("数据加密,将明文转换为密文:");
String es = "";
for (int i = 0; i < plainText.length(); i++) {
String c = String.valueOf(plainText.charAt(i)%7);
es+=c;
}
System.out.println(es);
return es;
}
}
5.客户端测试类
/**
* @author WxrStart
* @create 2022-05-31 16:52
*/
public class Client {
public static void main(String[] args) {
EncryptFacade ef = new EncryptFacade();
ef.fileEncrypt("E:\\IDEAwokspace\\test\\src\\main\\java\\com\\menmian\\hello.txt",
"E:\\IDEAwokspace\\test\\src\\main\\java\\com\\menmian\\hellojiami.txt");
}
}