11-外观模式

外观模式

例子:两种喝茶方式示意图

image-20221205201930589

外观模式:增加外观类降低客户类与业务类(子系统类)之间的耦合度(迪米特法则

为复杂子系统提供一个简单的访问入口

image-20221205202214064
  • 一个客户类需要和多个业务类交互,而这些需要交互的业务类经常会作为一个整体出现

  • 引入一个新的==外观类(Facade)来负责和多个业务类【子系统(Subsystem)】==进行交互,而客户类只需与外观类交互

  • 为多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互

分析示意图

image-20221205202851500

外观类将客户类与子系统的内部复杂性分隔开

  • 没有外观类:每个客户类需要和多个子系统之间进行复杂的交互,系统的耦合度很大

  • 引入外观类:客户类只需要直接与外观类交互,客户类与子系统之间原有的复杂引用关系由外观类来实现,从而降低了系统的耦合度

外观模式的定义

image-20221205203043036

(广义)接口:一组方法的集合。

对象结构型模式

  • 又称为门面模式
  • 迪米特法则的一种具体实现
  • 通过引入一个新的外观角色降低原有系统的复杂度,同时降低客户类与子系统之间的耦合度
  • 所指的子系统是一个广义的概念,它可以是一个类、一个功能模块、系统的一个组成部分或者一个完整的系统

外观模式结构

image-20221205203328047

增加子系统时都会违反开闭原则

image-20221205203945188

外观模式包含以下2个角色:
  • Facade(外观角色)

  • SubSystem(子系统角色)

子系统类典型代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SubSystemA {
public void methodA() {
//业务实现代码
}
}
public class SubSystemB {
public void methodB() {
//业务实现代码
}
}
public class SubSystemC {
public void methodC() {
//业务实现代码
}
}
外观类典型代码
1
2
3
4
5
6
7
8
9
10
11
public class Facade {
private SubSystemA obj1 = new SubSystemA();
private SubSystemB obj2 = new SubSystemB();
private SubSystemC obj3 = new SubSystemC();

public void method() {
obj1.methodA();
obj2.methodB();
obj3.methodC();
}
}
客户类典型代码
1
2
3
4
5
6
public class Client {
public static void main(String args[]) {
Facade facade = new Facade();
facade.method();
}
}
实例类图
image-20221205204124269 image-20221205204138223

(1) FileReader:文件读取类,充当子系统类

(2) CipherMachine:数据加密类,充当子系统类

(3) FileWriter:文件保存类,充当子系统类

(4) EncryptFacade:加密外观类,充当外观类

(5) Client:客户端测试类

扩展:凯撒加密

抽象外观类⭐️

动机
  • 在标准的外观模式结构图中,如果需要增加、删除或更换与外观类交互的子系统类,必须修改外观类或客户端的源代码,这将违背开闭原则

  • 可以通过引入抽象外观类对系统进行改进,在一定程度上解决该问题

模式结构

image-20221212191638186

抽象外观类代码实现
抽象外观类代码
1
2
3
public abstract class AbstractEncryptFacade {
public abstract void fileEncrypt(String fileNameSrc, String fileNameDes);
}
配置文件
1
2
3
4
<?xml version="1.0"?>
<config>
<className>designpatterns.facade.NewEncryptFacade</className>
</config>
实体外观类代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class NewEncryptFacade extends AbstractEncryptFacade {
private FileReader reader;
private NewCipherMachine cipher;
private FileWriter writer;

public NewEncryptFacade() {
reader = new FileReader();
cipher = new NewCipherMachine();
writer = new FileWriter();
}

public void fileEncrypt(String fileNameSrc, String fileNameDes) {
String plainStr = reader.read(fileNameSrc);
String encryptStr = cipher.encrypt(plainStr);
writer.write(encryptStr,fileNameDes);
}
}
客户端代码
1
2
3
4
5
6
public class Client {
public static void main(String args[]) {
AbstractEncryptFacade ef;
ef = (AbstractEncryptFacade)XMLUtil.getBean();
ef.fileEncrypt("src//designpatterns//facade//src.txt","src//designpatterns //facade//des.txt"); }
}

外观模式与单例模式联用

将外观类转变成单例类
image-20221212192413219

模式优点

  1. 对客户端屏蔽了子系统组件减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易

  2. 实现了子系统与客户端之间的松耦合关系,这使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可

  3. 子系统的内部变化不会影响到外观对象,一个子系统的修改对其他子系统也没有任何影响

模式缺点

  1. 不能很好地限制客户端直接使用子系统类,如果对客户端访问子系统类做太多的限制则减少了可变性和灵活性

    • 外观类提供统一地使用子系统的接口,但是并不限制客户类使用单个子系统
  2. 如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则

模式适用环境

  1. 要为访问一系列复杂的子系统提供一个简单入口

  2. 客户端程序多个子系统之间存在很大的依赖性

  3. 在层次化结构中,可以使用外观模式来定义系统中每一层的入口,层与层之间不直接产生联系,而是通过外观类建立联系,降低层之间的耦合度

    • image-20221212194557415
    • 在两层之间增加一个处理器,让view层与controller层之间不再直接访问,而是通过处理器进行联系,同时可以通过xml配置文件更换处理器。
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2023-2024 Guijie Wang
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信