使用Java的代理模式
首先
我将总结我在阅读《Java言語で学ぶデザインパターン入門》这本介绍GoF设计模式的增补改订版的书中学到的内容。
代理模式
Proxy是什么?
将其翻译为中文:
日语中翻译成中文意为“代理”。
代理模式是指代理类替代原本类进行一定程度的处理,直到真正需要原本类才进行原本类的生成的模式,也被称为代理模式。
通过应用该模式,可以解决在生成原本类时需要进行耗时的初始化处理,给用户带来不满的问题。
出场角色

抽象类/接口
Subject
ClientクラスからみてProxyクラスとRealSubjectクラスを同様に扱う(同一視する)ための抽象クラス/インタフェースです。
実装はサブクラスのProxyクラス、RealSubjectクラスで行います。
实现类
-
- Proxy
-
- RealSubjectクラスの代理役となるクラスです。
-
- Clientクラスからの要求に対してできるだけの処理を行い、本当に必要になった際にRealSubjectクラスのインスタンスを生成します。
-
- またSubjectクラス/インタフェースの実装を行い、フィールドとして本人役のRealSubjectクラスを持ちます。
-
- RealSubject
-
- 本人役となるクラスです。
-
- Proxyクラスで要求を処理しきれなかった際に生成されます。また、Proxyクラスと同様にSubjectクラス/インタフェースの実装を行います。
-
- Client
- Proxyクラスを経由してRealSubjectクラスを使用するクラスです。
具体的例子

界面
Managementインタフェース
public interface Management {
void setReviewProjectName(String projectName);
String getReviewProjectName();
void printReviewResult();
}
在Management接口中,定义了设置和获取projectName以及显示审核结果的方法。
实际的处理将在后面的Manager类和ManagerProxy类中实现。
没有特别困难的地方。
实现类
- Managerクラス
import java.util.Random;
public class Manager implements Management {
private String projectName;
public Manager() {
this.projectName = "無題の案件";
heavyJob("Managementのインスタンスを生成し、Rv中");
}
public Manager(String projectName) {
this.projectName = projectName;
heavyJob("Managementのインスタンス(" + projectName + ")を生成し、Rv中");
}
@Override
public void setReviewProjectName(String projectName) {
this.projectName = projectName;
}
@Override
public String getReviewProjectName() {
return projectName;
}
private void heavyJob(String msg) { // 1.生成時に必要(という設定)な重い処理
System.out.print(msg);
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.print("・");
}
System.out.println("Rv完了。");
}
@Override
public void printReviewResult() { // 2.乱数によってreviewの結果を振り分けて出力する処理
System.out.println("----------Rv結果----------");
Random rnd = new Random();
int ran = rnd.nextInt(10);
if (ran < 5) {
System.out.println(projectName + "は却下されました。\n");
} else if (ran > 5) {
System.out.println(projectName + "は承認されました。\n");
}
}
}
经理类是代表本人职责的类。代理职责的ManagerProxy类执行无法处理的操作。
在这里,printReviewResult方法执行这个操作。
重点有以下两点:
1. 构造函数中调用了heavyJob方法,这是一个在生成时需要而且耗时繁重的操作。
2. 覆盖了printReviewResult方法,显示审核结果。
进行补充说明。
生成Manager类时,需要首先执行heavyJob方法作为初始设置。然而,这个处理过程很繁重且耗时,因此在代理人角色的ManegerProxy类中,在调用无法处理的操作(printReviewResult)之前不宜生成Manager类。因此,后述的ManegerProxy类只负责获取和设置项目名称(getReviewProjectName,setReviewProjectName)等操作,而代理人角色本身在调用printReviewResult时会生成和设置真正的Manager类。
ManagerProxyクラス
public class ManagerProxy implements Management {
private String projectName;
private Manager real;
public ManagerProxy() {
this.projectName = "無題の案件";
}
public ManagerProxy(String projectName) {
this.projectName = projectName;
}
@Override
public synchronized void setReviewProjectName(String projectName) {
// 1.本人役が生成・設定されていれば本人役にプロジェクト名を設定する。
if (real != null) {
real.setReviewProjectName(projectName);
}
// 1.本人役が生成・設定されていなければ代理人役にプロジェクト名を設定する。
this.projectName = projectName;
}
@Override
public String getReviewProjectName() {
return projectName;
}
@Override
public void printReviewResult() {
realize();
real.printReviewResult();
}
private synchronized void realize() {// 2.本人役が生成・設定されていない場合に本人役を生成・設定する
if (real == null) {
real = new Manager(projectName);
}
}
}
ManagerProxy类是Manager类的代理类。
重点在于以下两点:
1. 重写了setReviewProjectName方法。
2. 在printReviewResult方法内调用了realize方法后,再调用了本身的printReviewResult方法。
1. 当调用setReviewProjectName时,如果本人角色的Manager类没有设置或生成,那么代理人角色的ManagerProxy将会设置projectName的值。此时,可以说本人角色的Manager类没有被生成,而是由代理人角色的ManagerProxy代替进行处理。
2. 由于printReviewResult方法对于代理人角色来说是无法处理的,所以在本人角色的Manager类没有被生成或设置的情况下,会进行生成和设置。
执行类
- Clientクラス
public class Client {
public static void main(String[] args) {
Management m1 = new ManagerProxy("A案件");
System.out.println("プロジェクトRvを開始します。");
System.out.println("Rv中のプロジェクトは" + m1.getReviewProjectName() + "です。");
m1.setReviewProjectName("B案件");
System.out.println("Rv中のプロジェクトは" + m1.getReviewProjectName() + "です。");
m1.printReviewResult();
Management m2 = new ManagerProxy();
System.out.println("プロジェクトRvを開始します。");
System.out.println("Rv中のプロジェクトは" + m2.getReviewProjectName() + "です。");
m2.setReviewProjectName("C案件");
System.out.println("Rv中のプロジェクトは" + m2.getReviewProjectName() + "です。");
m2.printReviewResult();
}
}
我正在创建ManagerProxy类的实例并设置名称获取。然后,通过调用printReviewResult方法,我创建了Manager类实例,以执行处理。
执行结果
在执行Client.java后的结果如下所示。可以看出,在执行重要的处理(heavyJob)之后,根据随机数输出了随机的Rv结果。
プロジェクトRvを開始します。
Rv中のプロジェクトはA案件です。
Rv中のプロジェクトはB案件です。
Managementのインスタンス(B案件)を生成し、Rv中・・・・・Rv完了。
----------Rv結果----------
B案件は却下されました。
プロジェクトRvを開始します。
Rv中のプロジェクトは無題の案件です。
Rv中のプロジェクトはC案件です。
Managementのインスタンス(C案件)を生成し、Rv中・・・・・Rv完了。
----------Rv結果----------
C案件は承認されました。
优点
代理模式的好处如下:
1. 可以缩短初始化所需的时间,提高用户的便利性。
2. 通过将代理对象和本体对象分开,可以实现组件化。
总结
直到真正需要时,我们才学习了代理模式,让代理人来处理事务而不是本人。
如果方便的话,请参考以下提供的示例代码。
- Proxyサンプルコード
此外,关于其他设计模式,我们在下面进行了总结,请参考。
- [随時更新]Javaでデザインパターンまとめ
请查阅引用资料。
- 増補改訂版 Java言語で学ぶデザインパターン入門