java - 代理模式 : how is it more efficent that creating the real object?

标签 java design-patterns proxy-pattern

在下面的例子中,来自维基书籍https://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Proxy

我不确定这比仅仅创建真实对象并使用它的显示图像更快/更有效。因为代理在 displayImage 方法中创建了真实的对象?

//on System B
    class ProxyImage implements Image {

        private RealImage image = null;
        private String filename = null;
        /**
         * Constructor
         * @param FILENAME
         */
        public ProxyImage(final String FILENAME) {
            filename = FILENAME;
        }

        /**
         * Displays the image
         */
        public void displayImage() {
            if (image == null) {
               image = new RealImage(filename);
            }
            image.displayImage();
        }

    }

如果您不使用代理,代理模式肯定不会节省内存,因为它需要实例化两个对象(代理和真实)而不是一个(真实)?

最佳答案

从您发布的链接(强调我的):

The proxy class ProxyImage is running on another system than the real image class itself and can represent the real image RealImage over there. The image information is accessed from the disk. Using the proxy pattern, the code of the ProxyImage avoids multiple loading of the image, accessing it from the other system in a memory-saving manner.

简而言之:它不会节省内存,它会加快应用程序的速度,因为您不需要每次都访问磁盘来读取真实图像。

这部分代码证明了这一点:

public void displayImage() {
    //if image is not loaded into memory
    if (image == null) {
        //then load it, go to disk only once
        image = new RealImage(filename);
    }
    //now it is in memory, display the real image
    image.displayImage();
}

为了更好地理解这个问题,让我们更改类和接口(interface)的定义:

public interface Image {
    String getName();
    byte[] getData();
}

现在,RealImage 类将始终在磁盘中寻找数据,以防文件不存在(已删除或重命名):

public class RealImage implements Image {
    //implements all the operations going to disk...
    private String fileName;
    public RealImage(String fileName) {
        this.fileName = fileName;
    }
    @Override
    public String getName() {
        String name = "";
        //fancy operations to seek for the file in disk (in case it has been deleted)
        //read the data from file in disk
        //get the name
        name = ...;
        return name;
    }
    @Override
    public byte[] getData() {
        byte[] data;
        //again, fancy operations to seek for the file in disk (in case it has been deleted)
        //read the data from file in disk
        //get the image data for displaying purposes
        data = ...;
        return data;
    }
}

现在,我们好的 ProxyImage 将充当 RealImage 的代理,通过将数据保存到内存中来节省每次转到磁盘的高成本任务:

public class ProxyImage implements Image {
    private String fileName;
    private RealImage realImage;
    private byte[] data;
    private String name;
    //implements all the operations going to disk...
    public RealImage(String fileName) {
        this.fileName = fileName;
    }
    @Override
    public String getName() {
        //in case we don't have the name of the image
        if (this.name == null) {
            //use a RealImage to retrieve the image name
            //we will create the instance of realImage only if needed
            if (realImage == null) {
                realImage = new RealImage(fileName);
            }
            //getting the image from the real image is highly costly
            //so we will do this only once
            this.name = realImage.getName();
        }
        return this.name;
    }
    @Override
    public byte[] getData() {
        //similar behavior for the data of the image
        if (this.data == null) {
            if (realImage == null) {
                realImage = new RealImage(fileName);
            }
            //highly costly operation
            this.data = realImage.getData();
        }
        return this.data;
    }
}

因此反射(reflect)了为我们的 RealImage 使用代理的优点

关于java - 代理模式 : how is it more efficent that creating the real object?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23297314/

相关文章:

Java Scanner nextDouble 命令使用 switch case 跳过值?

design-patterns - 如何动态实现代理模式?

javascript - 混合构造函数并在 Javascript 代理对象上应用陷阱

java - 水平滚动功能

java - 如何修复 404 错误,源服务器未找到目标资源的当前表示或不愿意透露该表示存在

java - 如何解码谷歌折线算法?

c# - 您使用什么规则来描述 MVP 方法和成员

design-patterns - 红/黑部署和蓝/绿部署有什么区别?

java - 在 MVC Java 游戏中将声音放在哪里?

oop - 代理模式和装饰者模式的区别