结构型模式
代理模式(Proxy Pattern)
代理模式(Proxy Pattern)是一种结构型设计模式,它通过引入一个代理对象来控制对另一个对象的访问。这个代理对象可以为被代理的对象提供额外的功能,例如访问控制、延迟初始化、日志记录、或网络访问等。
适用场景
-
远程代理:
- 为一个对象在不同的地址空间提供局部代表。
-
虚拟代理:
- 根据需要创建开销很大的对象。
-
保护代理:
- 控制对原始对象的访问。
-
智能指引:
- 在访问对象时执行一些附加操作,例如计数操作或引用检测。
实现示例(Java)
以下是一个简单的代理模式的实现示例,展示如何通过代理对象控制对实际对象的访问。
1. 定义主题接口
java
public interface Subject {
void request();
}
- 说明 :
Subject
接口定义了一个request
方法,这是实际对象和代理对象都需要实现的方法。
2. 定义真实主题类(RealSubject)
java
public class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
- 说明 :
RealSubject
类实现了Subject
接口的request
方法,表示真实处理请求的类。
3. 定义代理类(Proxy)
java
public class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
public void request() {
if (this.checkAccess()) {
this.realSubject.request();
this.logAccess();
}
}
private boolean checkAccess() {
// 检查访问权限
System.out.println("Proxy: Checking access prior to firing a real request.");
return true;
}
private void logAccess() {
// 记录请求日志
System.out.println("Proxy: Logging the time of request.");
}
}
- 说明 :
Proxy
类实现了Subject
接口,并持有一个RealSubject
对象。- 在
request
方法中,代理类先检查访问权限,再调用真实对象的request
方法,最后记录请求日志。
4. 客户端代码
java
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.request();
}
}
- 说明 :
Client
类创建了RealSubject
和Proxy
对象,通过Proxy
对象调用request
方法,从而控制对RealSubject
的访问。
优点
-
隔离性:
- 代理模式可以作为调用者和实际对象之间的中介,降低系统组件之间的耦合度,增强对象间的隔离性。
-
安全性:
- 通过代理可以控制对实际对象的访问,实现安全检查以及深度验证。
-
扩展性:
- 代理模式在不修改具体对象代码的情况下,可以灵活地增加功能。
-
智能化:
- 可以在不改变服务对象接口的前提下,实施一些附加操作,如延迟初始化和访问日志等。
缺点
-
代码复杂性:
- 引入代理也意味着增加了系统的复杂性,可能会引入新的类和接口,增加了代码的理解和维护成本。
-
响应时间:
- 代理模式可能会导致系统运行速度减慢,特别是在代理操作中加入了大量处理逻辑时。
-
设计难度:
- 正确地设计和实施代理模式需要仔细考虑整个系统的设计,以确保不会对系统性能产生负面影响。
类图
Client
|
v
Subject <---- Proxy <---- RealSubject
总结
代理模式提供了一种有效的方式来控制和管理对象的访问。通过使用代理,可以在保持业务对象职责清晰的同时,增加各种功能。此模式特别适用于需要对业务对象进行访问控制和其他预处理操作的场景。
外观模式(Facade Pattern)
外观模式(Facade Pattern)是一种结构型设计模式,它通过提供一个统一的接口,用来访问子系统中的一群接口,从而让复杂子系统更容易使用。外观模式定义了一个高层接口,使得这一子系统更加容易使用。
适用场景
-
简化复杂系统的接口:
- 为复杂的子系统提供一个简单的接口,减少外部与子系统的交互复杂度。
-
层次结构:
- 在多层系统结构中,可以使用外观模式定义每层的入口,简化层之间的依赖关系。
-
解耦系统:
- 通过引入外观模式,使得子系统与客户端之间的耦合度降低。
实现示例(Java)
以下是一个简单的外观模式的实现示例,展示如何通过外观类简化对子系统的使用。
1. 定义子系统类
java
public class SubsystemA {
public void operationA() {
System.out.println("SubsystemA: operationA");
}
}
public class SubsystemB {
public void operationB() {
System.out.println("SubsystemB: operationB");
}
}
public class SubsystemC {
public void operationC() {
System.out.println("SubsystemC: operationC");
}
}
2. 定义外观类
java
public class Facade {
private SubsystemA subsystemA;
private SubsystemB subsystemB;
private SubsystemC subsystemC;
public Facade() {
this.subsystemA = new SubsystemA();
this.subsystemB = new SubsystemB();
this.subsystemC = new SubsystemC();
}
public void operation1() {
System.out.println("Facade: operation1");
subsystemA.operationA();
subsystemB.operationB();
}
public void operation2() {
System.out.println("Facade: operation2");
subsystemB.operationB();
subsystemC.operationC();
}
}
3. 客户端代码
java
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.operation1();
facade.operation2();
}
}
注释说明
-
子系统类:
SubsystemA
,SubsystemB
, 和SubsystemC
是子系统的具体实现类,每个类都有自己独特的操作方法。
-
外观类:
Facade
类持有子系统的对象,并提供简化的接口operation1
和operation2
来调用子系统的功能。
-
客户端代码:
Client
类通过Facade
类来调用operation1
和operation2
,从而简化了对复杂子系统的使用。
优点
-
简化接口:
- 外观模式为子系统提供了一个简单的接口,减少了与子系统交互的复杂度。
-
松散耦合:
- 外观模式使得子系统与客户端之间的耦合度降低,有助于提高系统的可维护性和扩展性。
-
更好的分层:
- 外观模式有助于建立一个清晰的分层结构,定义每层的入口。
缺点
-
不符合开闭原则:
- 增加新的子系统功能时,可能需要修改外观类,违背了开闭原则(对扩展开放,对修改关闭)。
-
可能造成性能问题:
- 在某些情况下,使用外观模式可能会导致系统性能下降,因为所有请求都需要经过外观类。
类图
Client
|
v
Facade ----> SubsystemA
----> SubsystemB
----> SubsystemC
总结
外观模式通过提供一个简化的接口,使得复杂子系统的使用变得更加容易。它适用于需要简化子系统接口、减少客户端与子系统直接交互、解耦系统层次结构的场景。尽管它有可能违反开闭原则,但在大多数情况下,它的优点远远超过其缺点,使得系统设计更加清晰和易于维护。