`

代理模式Image Proxies(一、最朴素实现)

阅读更多

A Classic Example:  Image Proxies

       以下是最朴素的代理模式实现,其中只有“代理”的思想,但并不是真正的代理。



 

       一个ImageIconProxy proxy实例被封装在JFrame frame中,且他们都是ShowProxy属性。

       点击“Load按钮”触发调用proxy.load(frame),该方法重新设置proxy内部current对象为ImageIcon LOADING,立即repaint窗口frame,将短暂显示Loading…。然后,该方法启动独立线程加载最终图片,这个独立线程也是通过重新设置proxy内部current对象,然后重绘(调用callbackFrame.pack())的方式。

       重绘通过ImageIconProxy实现以下三个方法:

       getIconHeight()getIconWidth()paintIcon(...),实现时只需将ImageIconProxycurrent指示的图片绘制出来。注意到,ImageIconProxy继承了ImageIcon,并实现了该父类的此三种方法后就可以被调用者当作一个ImageIcon实例使用了。

 

代码:

文件一:ShowProxy.java

package app.proxy;

 

public class ShowProxy implements ActionListener {

    private ImageIconProxy proxy = new ImageIconProxy("images/fest.jpg");

    private JFrame frame;

    private JButton loadButton;

 

    /*********************************Load按钮*******************************/

    protected JButton loadButton() {

        if (loadButton == null) {

            loadButton = new JButton("Load");

            loadButton.addActionListener(this);//ShowProxy实现监听按钮

            loadButton.setFont(SwingFacade.getStandardFont());

        }

        return loadButton;

    }

   

    /**

     * 当用户点击按钮时,触发监听器执行这个函数

     * Start loading the image and disable the Load button.

     */

    public void actionPerformed(ActionEvent e) {

    /*

     * 理解P117这句话:

     * The proxy does its work by judiciously forwarding requests to

     * the underlying object that the proxy controls access to.

     */

        proxy.load(frame);    //这里是关键!!!

        loadButton().setEnabled(false);

    }

 

    /*********************************JPanel**********************************/

    protected JPanel mainPanel() {

        JPanel p = new JPanel();

        p.setLayout(new BorderLayout());

       

        /*

         * ImageIconProxy被封装在JLabel内部-->

         * JLabel(Icon);

         * ImageIconProxy extends ImageIcon;

         * ImageIcon implements javax.swing.Icon

         */

        p.add("Center", new JLabel(proxy));

        /*

         * 添加按钮到JPanel,点击按钮后调用方法:

         * proxy.load(frame);

         */

        p.add("South", loadButton());

        return p;

    }

    /*********************************main()**********************************/

    public static void main(String[] args) {

        ShowProxy sp = new ShowProxy();

        sp.frame = SwingFacade.launch(sp.mainPanel(), " Proxy");

        /*

         * 1. com.oozinoz.ui.SwingFacade:

         * This utility class provides an interface that makes

         * the Swing subsystem easy to use.

         *

         * 2. JFrame com.oozinoz.ui.SwingFacade.launch(Component c, String title):

         * Display the given component within a frame.

         */

    }

}

 

文件二:ImageIconProxy.java  -->  可以看做是代理

public class ImageIconProxy extends ImageIcon implements Runnable {

    static final ImageIcon ABSENT = new ImageIcon(ClassLoader

            .getSystemResource("images/absent.jpg"));

    static final ImageIcon LOADING = new ImageIcon(ClassLoader

            .getSystemResource("images/loading.jpg"));

   

    ImageIcon current = ABSENT;//只会显示current指示的图片

    protected String filename;

    protected JFrame callbackFrame;

 

    public ImageIconProxy(String filename) {

        super(ABSENT.getImage());// Image javax.swing.ImageIcon.getImage()

        this.filename = filename;

    }

 

    public void load(JFrame callbackFrame) {

        //1、将图片设置为LOADING

        this.callbackFrame = callbackFrame;

        current = LOADING;

        callbackFrame.repaint();

       

        //2、利用一个独立线程,加载最终图片

        /*

         * 仅当点击Load按钮时,触发proxy.load(frame);(在类ShowProxy)

         * 初始时,ImageIconProxy被实例化,但并没有启动它的线程

         */

        new Thread(this).start();

    }

 

    public void run() {

        current = new ImageIcon(ClassLoader.getSystemResource(filename));

        /*

         * void java.awt.Window.pack():

         * Causes this Window to be sized to fit the preferred size and

         * layouts of its subcomponents...

         */

        callbackFrame.pack();

    }

 

    public int getIconHeight() {

        return current.getIconHeight();

    }

 

    public int getIconWidth() {

        return current.getIconWidth();

    }

 

    /**

     * Paint the Icon

     */

    public synchronized void paintIcon(Component c, Graphics g, int x, int y) {

        current.paintIcon(c, g, x, y);

    }

}

 

Q&A:

The ImageIconProxy class is not a well-designed, reusable component. Point out two problems with the design.

 

1.     Forwarding only a subset of calls to an underlying ImageIcon object is dangerous. The ImageIconProxy class inherits a dozen fields and at least 25 methods from the ImageIcon class. To be a true proxy, the ImageIconProxy object needs to forward most or all of these calls. Thorough forwarding would require many potentially erroneous methods, and this code would require maintenance as the ImageIcon class and its superclasses change over time.

     (ImageIconProxy对象)仅向底层的ImageIcon对象转发部分调用是危险的。ImageIconProxy对象从ImageIcon类集成了一打域和至少25个方法。作为一个真正的代理,ImageIconProxy必须转发大多数或全部调用。“完全转发”可能导致潜在错误,而且这样的代码要求随ImageIcon类及其父类改变而改变。

 

2.     You might question whether the “Absent” image and the desired image are in the right places in the design. It might make more sense to have the images passed in rather than making the class responsible for finding them.

 

      你或许对"Absent"图片和最终图片的位置争取性存在疑问。或许让这些图片被传入,而非让ImageIconProxy来负责他们,更加合理。

 

 

见附件中使用oozinoz提供的包简单实现窗口的代码

 

 

  • 大小: 28.2 KB
分享到:
评论

相关推荐

    代理模式Image Proxies(二、最朴素实现)

    在这个名为“代理模式Image Proxies”的主题中,我们将探讨如何通过最朴素的方式来实现图像加载的代理。这个话题主要涉及到两个Java类:`LoadingImageIcon.java`和`ShowLoader.java`。 `LoadingImageIcon.java`可能...

    代理模式Remote Proxies(三、RMI)

    代理模式在软件设计中是一种常用的设计模式,它允许我们为一个对象提供一个替代品或占位符,以便控制对真实对象的访问。在远程方法调用(Remote Method Invocation,RMI)场景下,代理模式的应用尤为突出。RMI是Java...

    proxies_chi.zip

    标题"proxies_chi.zip"和描述中提到的内容是关于创建一个代理IP池的Python项目,这个项目能够自动从网络上抓取IP地址,检查它们的可用性,并将这些信息存储到数据库中,以便后续使用。这涉及到网络爬虫、IP验证、...

    Laravel开发-laravel-valid-proxies

    当用户的请求通过一个代理服务器到达应用时,Laravel需要识别并处理这些代理头,以便正确地跟踪用户行为和处理请求。这涉及到设置`trusted_proxies`配置,该配置在`config/Http/Kernel.php`文件的`$proxies`变量中...

    c#动态代理

    .NET Framework提供了两种主要的动态代理实现方式: 1. **System.Reflection.Emit**:这是.NET Framework提供的IL(中间语言)生成API,可以直接在运行时动态地构建类型。通过Emit API,我们可以生成包含代理逻辑的...

    Python实现 windows 下代理IP的自动切换

    在IT行业中,网络爬虫和自动化测试等场景经常需要使用代理IP来避免因频繁请求而被目标网站封禁。本文将详细介绍如何使用Python在Windows环境...通过合理设计和实现,我们可以构建一个稳定且高效的代理IP自动切换系统。

    用Proxies实现对象撤消使重做和更改历史记录

    为实现这一功能,开发者常常利用设计模式来辅助,其中一种常用的方法是使用"代理"(Proxies)。本文将详细探讨如何通过JavaScript的Proxy对象来实现对象撤消/重做以及记录更改历史。 首先,让我们理解什么是Proxy。...

    Java Networking and Proxies Code

    本文将详细解析"Java Networking and Proxies Code"这一主题,包括如何启动一个线程来检查URL是否通过代理以及如何获取代理的详细信息。 首先,让我们了解一下Java中的网络编程基础。Java提供了`java.net`包,该包...

    Csharp设计模式

    在C#中,可以使用虚方法、抽象类或接口实现静态代理,或者利用.NET的`System.Runtime.Remoting.Proxies`命名空间实现动态代理。 9. **适配器模式(Adapter)**:将一个类的接口转换成客户希望的另一个接口。适配器...

    koa-proxies:koa@2.x代理中间件

    Koa代理 middlware HTTP代理 由提供支持。 安装 $ npm install koa-proxies --save 选件 http-proxy活动 options . events = { error ( err , req , res ) { } , proxyReq ( proxyReq , req , res ) { } , ...

    Laravel开发-laravel-valid-proxies .zip.zip

    在本文中,我们将深入探讨Laravel框架中的代理验证(laravel-valid-proxies)这一主题。Laravel是一个流行的PHP框架,它提供了丰富的功能和工具,帮助开发者构建高效、优雅的Web应用。`laravel-valid-proxies`是...

    Delphi_Proxy_Scraper.zip_Proxies

    标题中的"Delphi_Proxy_Scraper.zip_Proxies"暗示了这是一个使用Delphi编程语言编写的代理服务器抓取程序。Delphi是一种基于Object Pascal的集成开发环境(IDE),常用于创建桌面应用程序。在这个项目中,开发者可能...

    python中requests使用代理proxies方法介绍

    如果需要使用代理,你可以通过为任意请求方法提供 proxies 参数来配置单个请求: import requests proxies = { "http": "http://10.10.1.10:3128", "https": "http://10.10.1.10:1080", } requests.get(...

    python3爬取快代理免费代理ip并多线程验证

    这通常通过向某个网站发送带有代理设置的请求来实现。Python的`requests`库支持设置代理,我们可以使用`proxies`参数。 3. **验证代理IP**: - 设置代理:`proxies = {'http': 'http://ip:port', '...

    Proxy is a high performance HTTPS proxies SOCKS5 proxiesWEB.zip

    标题 "Proxy is a high performance HTTPS proxies SOCKS5 proxiesWEB.zip" 暗示这是一个包含高性能HTTPS代理、SOCKS5代理以及WEB代理的压缩文件集合。这个文件可能被设计用于网络连接优化、匿名浏览或者多线程下载...

    scrapy-rotating-proxies:与Scrapy一起使用多个代理

    LIST_PATH选项,以及一个带有代理的文件的路径,每行一个: ROTATING_PROXY_LIST_PATH = '/my/path/proxies.txt'如果同时存在两个选项,则ROTATING_PROXY_LIST_PATH优先于ROTATING_PROXY_LIST 。

    PyPI 官网下载 | scrapy-scylla-proxies-0.1.4.1.tar.gz

    Scrapy-Scylla-Proxies 是一个 Python 库,专门用于Scrapy爬虫框架,它提供了高效且稳定的代理服务器管理功能。这个库的版本是0.1.4.1,可以在Python的包索引(PyPI)官网上找到并下载。在Python的开发中,PyPI是一...

    Python库 | proxies_l-0.0.3.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:proxies_l-0.0.3.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    代理超人可以提供免费代理IP自动换IP

    首先,代理IP是互联网上的一个中间节点,用户通过这个节点进行网络活动,隐藏了真实的IP地址,从而实现匿名浏览或者突破地域限制。代理超人的核心价值在于它能为用户免费提供这些IP资源,这对于预算有限或者偶尔需要...

Global site tag (gtag.js) - Google Analytics