使用Java的代理模式

首先

我将总结我在阅读《Java言語で学ぶデザインパターン入門》这本介绍GoF设计模式的增补改订版的书中学到的内容。

代理模式

Proxy是什么?

将其翻译为中文:

日语中翻译成中文意为“代理”。
代理模式是指代理类替代原本类进行一定程度的处理,直到真正需要原本类才进行原本类的生成的模式,也被称为代理模式。
通过应用该模式,可以解决在生成原本类时需要进行耗时的初始化处理,给用户带来不满的问题。

出场角色

image.png

抽象类/接口

Subject
ClientクラスからみてProxyクラスとRealSubjectクラスを同様に扱う(同一視する)ための抽象クラス/インタフェースです。
実装はサブクラスのProxyクラス、RealSubjectクラスで行います。

实现类

    • Proxy

 

    • RealSubjectクラスの代理役となるクラスです。

 

    • Clientクラスからの要求に対してできるだけの処理を行い、本当に必要になった際にRealSubjectクラスのインスタンスを生成します。

 

    • またSubjectクラス/インタフェースの実装を行い、フィールドとして本人役のRealSubjectクラスを持ちます。

 

    • RealSubject

 

    • 本人役となるクラスです。

 

    • Proxyクラスで要求を処理しきれなかった際に生成されます。また、Proxyクラスと同様にSubjectクラス/インタフェースの実装を行います。

 

    • Client

 

    Proxyクラスを経由してRealSubjectクラスを使用するクラスです。

具体的例子

image.png

界面

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言語で学ぶデザインパターン入門
bannerAds