在Java中使用代理设计模式


今天,我将讨论另一种结构设计模式-代理设计模式。代理是指充当另一个对象的对象。

Proxy设计模式

  • 该Proxy Design Pattern 是一个结构设计模式和一个四设计模式岗。
  • 该Proxy设计模式提供了一种方式来创建一个代表另一个类的功能的类。
  • 该Proxy 可以对接口的任何; 网络连接,内存中的大对象,文件或其他昂贵或无法复制的其他资源。
  • 该Proxy 就是这样被客户端调用访问幕后真正的服务对象的包装对象。
  • 该Proxy 对象隐藏到它原来的目标和控制访问。
  • 该Proxy 使用时,我们可能想创建一个可以以别的接口执行类。
  • 该Proxy 模式允许我们创建具有原始对象接口的功能,客户端应用程序对象。
  • 该Proxy 在对象的延迟加载执行最常用的。我的意思是创建代理对象来代替完整的实际对象,直到真正需要它为止。
  • 该Proxy 理 也可以被用来围绕所述真实对象添加了额外的安全层。
  • Proxy 通过提供虚拟的和自定义的实现来隐藏Real对象。
  • 我们可以通过多种方式进行代理,例如:

    • Virtual Proxy-延迟加载内存丰富或繁重的对象,直到需要它为止。
    • Virtual Proxy-就像在Decorator设计模式中一样,向现有对象添加额外的功能。
    • Virtual Proxy-控制对对象功能的访问。
    • Virtual Proxy-添加日志也可能有助于调试。
    • Virtual Proxy-为RMI / RPC或CORBA中的存根对象等远程对象提供本地代表。
    • Virtual Proxy-在更新时检查实际对象的锁定,在第一个引用上加载持久性对象,管理实际对象引用等。
  • 客户端应用程序可以使用类似于真实对象的代理对象, 因为两者都实现相同的接口。 代理 设计模式使用 三个组件来实现:

  • 主题 -公开功能的界面。
    • Real Subject-类实现Subject 并提供接口的具体实现。在此类中,我们隐藏在代理后面。
    • Proxy -类实现Subject, 以便它可以替代Real Subject对象。它维护对替代代理 对象的真实主体的引用,以便可以在需要时将请求转发到 真实主体。

让我们以一个例子来了解代理。

使用代理设计模式的图像加载应用程序 假设我们有一个 Image 界面来加载和操作图像,如下所示:

package org.trishinfotech.proxy;
public interface Image {
    public void load();
    public void show();
    public void showSummary();
    public void resize();
    public void remove();
    public void close();
}

现在有一个名为RealImage的具体类来处理本地图像文件:

package org.trishinfotech.proxy;
public class RealImage implements Image {

    protected String fileNameWithPath;

    public RealImage(String fileNameWithPath) {
        this.fileNameWithPath = fileNameWithPath;
        load();
    }

    @Override
    public void load() {
        System.out.println("RealImage: Loading image: " + fileNameWithPath);
    }

    @Override
    public void show() {
        System.out.println("RealImage: Showing image: " + fileNameWithPath);
    }
    @Override
    public void showSummary() {
        System.out.println("RealImage: Showing Summary of image: " + fileNameWithPath);
    }
    @Override
    public void resize() {
        System.out.println("RealImage: Resizing image: " + fileNameWithPath);

    }

    @Override
    public void remove() {
        System.out.println("RealImage: Removing image: " + fileNameWithPath);
    }

    @Override
    public void close() {
        System.out.println("RealImage: Closing image: " + fileNameWithPath);
    }

    public String getFileNameWithPath() {
        return fileNameWithPath;
    }

    public void setFileNameWithPath(String fileNameWithPath) {
        this.fileNameWithPath = fileNameWithPath;
    }

}

如您所见,该类在我们创建对象时加载图像(早期加载)。

现在,还有一个名为RemoteImage的 具体类,用于处理网络共享驱动器中存储的图像。

package org.trishinfotech.proxy;
public class RemoteImage implements Image {
    private String remoteHost;
    protected String fileNameWithPath;
    public RemoteImage(String remoteHost, String fileNameWithPath) {
        this.remoteHost = remoteHost;
        this.fileNameWithPath = fileNameWithPath;
        load();
    }

    @Override
    public void load() {
        System.out.printf("RemoteImage: Loading image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
    }

    @Override
    public void show() {
        System.out.printf("RemoteImage: Showing image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
    }

    @Override

    public void showSummary() {

        System.out.printf("RemoteImage: Showing Summary of image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
    }
    @Override
    public void resize() {
        System.out.printf("RemoteImage: Resizing image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
    }

    @Override
    public void remove() {
        System.out.printf("RemoteImage: Removing image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
    }

    @Override
    public void close() {
        System.out.printf("RemoteImage: Closing image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
    }
    public String getRemoteHost() {
        return remoteHost;
    }
    public void setRemoteHost(String remoteHost) {
        this.remoteHost = remoteHost;
    }

    public String getFileNameWithPath() {
        return fileNameWithPath;
    }

    public void setFileNameWithPath(String fileNameWithPath) {
        this.fileNameWithPath = fileNameWithPath;
    }

}

请注意,这两个类都是Image 接口的子类。

现在让我们创建一个代理类来解决:

  • 图像的延迟加载。
  • 添加安全层以调整大小和删除图像。
  • 在处理图像时添加日志和错误语句。

由于我有两个具体的Image接口类,因此我正在编写一个名为ProxyImage 的通用代理类来处理这两个类。我们也可以编写单独的代理。正如我已经提到的,代理类使我们成为相同接口或类的子类。即图像 在这种情况下。

package org.trishinfotech.proxy;
public class ProxyImage implements Image {

    protected String remoteHost;
    protected String fileNameWithPath;
    private Image image;
    protected boolean isAdmin;

    public ProxyImage(String fileNameWithPath, boolean isAdmin) {
        super();
        this.fileNameWithPath = fileNameWithPath;
        this.isAdmin = isAdmin;
    }

    public ProxyImage(String remoteHost, String fileNameWithPath, boolean isAdmin) {
        this(fileNameWithPath, isAdmin);
        this.remoteHost = remoteHost;
    }

    @Override
    public void load() {
        if (image == null) {
            if (remoteHost != null) {
                image = new RemoteImage(remoteHost, fileNameWithPath);
            } else {
                image = new RealImage(fileNameWithPath);
            }
        } else {
            System.err.printf("ImageProxy: Already loaded image: '%s'.\n", fileNameWithPath);
        }
    }

    @Override
    public void show() {
        load();
        image.show();
    }

    @Override
    public void showSummary() {
        System.err.printf("ImageProxy: Showing Summary of image: '%s'.\n", fileNameWithPath);
    }

    @Override
    public void resize() {
        if (isAdmin) {
            load();
            image.resize();
        } else {
            System.err.printf("ImageProxy: Only Admin can resize image: '%s'.\n", fileNameWithPath);
        }
    }

    @Override
    public void remove() {
        if (isAdmin) {
            load();
            image.resize();
        } else {
            System.err.printf("ImageProxy: Only Admin can remove image: '%s'.\n", fileNameWithPath);
        }
    }

    @Override
    public void close() {
        if (image != null) {
            image.close();
        } else {
            System.err.printf("ImageProxy: Already closed image: " + fileNameWithPath);
        }
    }

    public String getRemoteHost() {
        return remoteHost;
    }

    public void setRemoteHost(String remoteHost) {
        this.remoteHost = remoteHost;
    }

    public String getFileNameWithPath() {
        return fileNameWithPath;
    }
    public void setFileNameWithPath(String fileNameWithPath) {
        this.fileNameWithPath = fileNameWithPath;
    }

    public boolean isAdmin() {
        return isAdmin;
    }

    public void setAdmin(boolean isAdmin) {
        this.isAdmin = isAdmin;
    }

}

现在让我们编写一个Main 类来执行和测试我们的代码:

package org.trishinfotech.proxy;
public class Main {

    public static void main(String[] args) {
        System.out.println("Using Real Image class...");
        Image image1 = new RealImage("ABC.jpg");
        image1.showSummary();
        image1.load();
        image1.show();
        image1.resize();
        image1.close();
        image1.remove();
        System.out.println("------------------------------------------------");
        System.out.println("Using Proxy Image class...");
        Image image2 = new ProxyImage("ABC.jpg", true);
        image2.showSummary();
        image2.load();
        image2.show();
        image2.resize();
        image2.close();
        image2.remove();
        System.out.println("------------------------------------------------");
        System.out.println("Using Remote Image class...");
        Image image3 = new RemoteImage("192.168.0.1", "ABC.jpg");
        image3.showSummary();
        image3.load();
        image3.show();
        image3.resize();
        image3.close();
        image3.remove();
        System.out.println("------------------------------------------------");
        System.out.println("Using Proxy Image class...");
        Image image4 = new ProxyImage("192.168.0.1", "ABC.jpg", false);
        image4.showSummary();
        image4.load();
        image4.show();
        image4.resize();
        image4.close();
        image4.remove();
        System.out.println("------------------------------------------------");
    }

}

下面是程序的输出 :

Using Real Image class...
RealImage: Loading image: ABC.jpg
RealImage: Showing Summary of image: ABC.jpg
RealImage: Loading image: ABC.jpg
RealImage: Showing image: ABC.jpg
RealImage: Resizing image: ABC.jpg
RealImage: Closing image: ABC.jpg
RealImage: Removing image: ABC.jpg
------------------------------------------------
Using Proxy Image class...
ImageProxy: Showing Summary of image: 'ABC.jpg'.
RealImage: Loading image: ABC.jpg
ImageProxy: Already loaded image: 'ABC.jpg'.
ImageProxy: Already loaded image: 'ABC.jpg'.
ImageProxy: Already loaded image: 'ABC.jpg'.
RealImage: Showing image: ABC.jpg
RealImage: Resizing image: ABC.jpg
RealImage: Closing image: ABC.jpg
RealImage: Resizing image: ABC.jpg
------------------------------------------------
Using Remote Image class...
RemoteImage: Loading image: 'smb:\\192.168.0.1\ABC.jpg'.
RemoteImage: Showing Summary of image: 'smb:\\192.168.0.1\ABC.jpg'.
RemoteImage: Loading image: 'smb:\\192.168.0.1\ABC.jpg'.
RemoteImage: Showing image: 'smb:\\192.168.0.1\ABC.jpg'.
RemoteImage: Resizing image: 'smb:\\192.168.0.1\ABC.jpg'.
RemoteImage: Closing image: 'smb:\\192.168.0.1\ABC.jpg'.
RemoteImage: Removing image: 'smb:\\192.168.0.1\ABC.jpg'.
------------------------------------------------
Using Proxy Image class...
ImageProxy: Showing Summary of image: 'ABC.jpg'.
RemoteImage: Loading image: 'smb:\\192.168.0.1\ABC.jpg'.
ImageProxy: Already loaded image: 'ABC.jpg'.
RemoteImage: Showing image: 'smb:\\192.168.0.1\ABC.jpg'.
ImageProxy: Only Admin can resize image: 'ABC.jpg'.
RemoteImage: Closing image: 'smb:\\192.168.0.1\ABC.jpg'.
ImageProxy: Only Admin can remove image: 'ABC.jpg'.
------------------------------------------------


原文链接:http://codingdict.com