代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。


类图

设计模式——代理模式(Proxy Pattern)_Proxy Pattern

(图片源于网络)


代码实现(Java)

// ImageComponent.java
class ImageComponent extends JComponent {
    private Icon icon;
    public ImageComponent(Icon icon) {
        this.icon = icon;
    }
    public void setIcon(Icon icon) {
        this.icon = icon;
    }
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        int w = icon.getIconWidth();
        int h = icon.getIconHeight();
        int x = (800 - w)/2;
        int y = (600 - h)/2;
        icon.paintIcon(this, g, x, y);
    }
}


// ImageProxy.java
class ImageProxy implements Icon {
    ImageIcon p_w_picpathIcon;
    URL p_w_picpathURL;
    Thread retrievalThread;
    boolean retrieving = false;
                 
    public ImageProxy(URL url) { p_w_picpathURL = url; }
                 
    public int getIconWidth() {
        if (p_w_picpathIcon != null) {
            return p_w_picpathIcon.getIconWidth();
        } else {
            return 800;
        }
    }
             
    public int getIconHeight() {
        if (p_w_picpathIcon != null) {
            return p_w_picpathIcon.getIconHeight();
        } else {
            return 600;
        }
    }
                 
    public void paintIcon(final Component c, Graphics  g, int x,  int y) {
        if (p_w_picpathIcon != null) {
            p_w_picpathIcon.paintIcon(c, g, x, y);
        } else {
            g.drawString("Loading CD cover, please wait...", x+300, y+190);
            if (!retrieving) {
                retrieving = true;
                retrievalThread = new Thread(new Runnable() {
                    public void run() {
                        try {
                            p_w_picpathIcon = new ImageIcon(p_w_picpathURL, "CD Cover");
                            c.repaint();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
                retrievalThread.start();
            }
        }
    }
}


测试代码

// ImageProxyTestDrive.java
public class ImageProxyTestDrive {
    ImageComponent p_w_picpathComponent;
    JFrame frame = new JFrame("CD Cover Viewer");
    JMenuBar menuBar;
    JMenu menu;
    Hashtable cds = new Hashtable();
          
    public static void main (String[] args) throws Exception {
        ImageProxyTestDrive testDrive = new ImageProxyTestDrive();
    }
          
    public ImageProxyTestDrive() throws Exception{
        cds.put("Ambient: Music for Airports","http://p_w_picpaths.amazon.com/p_w_picpaths/P/B000003S2K.01.LZZZZZZZ.jpg");
        cds.put("Buddha Bar","http://p_w_picpaths.amazon.com/p_w_picpaths/P/B00009XBYK.01.LZZZZZZZ.jpg");
        cds.put("Ima","http://p_w_picpaths.amazon.com/p_w_picpaths/P/B000005IRM.01.LZZZZZZZ.jpg");
        cds.put("Karma","http://p_w_picpaths.amazon.com/p_w_picpaths/P/B000005DCB.01.LZZZZZZZ.gif");
        cds.put("MCMXC A.D.","http://p_w_picpaths.amazon.com/p_w_picpaths/P/B000002URV.01.LZZZZZZZ.jpg");
        cds.put("Northern Exposure","http://p_w_picpaths.amazon.com/p_w_picpaths/P/B000003SFN.01.LZZZZZZZ.jpg");
        cds.put("Selected Ambient Works, Vol. 2","http://p_w_picpaths.amazon.com/p_w_picpaths/P/B000002MNZ.01.LZZZZZZZ.jpg");
        URL initialURL = new URL((String)cds.get("Selected Ambient Works, Vol. 2"));
        menuBar = new JMenuBar();
        menu = new JMenu("Favorite CDs");
        menuBar.add(menu);
        frame.setJMenuBar(menuBar);
        for(Enumeration e = cds.keys(); e.hasMoreElements();) {
            String name = (String)e.nextElement();
            JMenuItem menuItem = new JMenuItem(name);
            menu.add(menuItem);
            menuItem.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent event) {
                     p_w_picpathComponent.setIcon(new ImageProxy(getCDUrl(event.getActionCommand())));
                    frame.repaint();
                  }
            });
        }
                 
        // set up frame and menus
          
        Icon icon = new ImageProxy(initialURL);
        p_w_picpathComponent = new ImageComponent(icon);
        frame.getContentPane().add(p_w_picpathComponent);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800,600);
        frame.setVisible(true);
    }
    URL getCDUrl(String name) {
        try {
            return new URL((String)cds.get(name));
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null;
        }
    }
}


运行效果

设计模式——代理模式(Proxy Pattern)_代理模式_02