定义 虚拟代理作为创建开销大的对象的代表。虚拟代理经常直到我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由虚拟代理来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。
场景 可以显示CD封面的Swing应用
场景介绍 建立一个应用程序,用来展现你最喜欢的CD封面。应用程序提供一个下拉菜单,然后从相应网站取得对应的CD封面。已知,限于连接带宽和网络负载,下载可能需要一些时间,所以在等待图像加载的时候,应该给出一些友好的提示。要求在等待图像时整个应用程序不要被挂起。一旦图像加载完成,Swing组件上显示相应的图像。
解决方案 ImageProxy
代理用于隐藏创建开销大的对象(因为我们需要通过网络获取图像数据)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import java.net.*;import java.awt.*;import javax.swing.*;class ImageProxy implements Icon { volatile ImageIcon imageIcon; final URL imageURL; Thread retrievalThread; boolean retrieving = false ; public ImageProxy (URL url) { imageURL = url; } public int getIconWidth () { if (imageIcon != null ) { return imageIcon.getIconWidth(); } else { return 800 ; } } public int getIconHeight () { if (imageIcon != null ) { return imageIcon.getIconHeight(); } else { return 600 ; } } synchronized void setImageIcon (ImageIcon imageIcon) { this .imageIcon = imageIcon; } public void paintIcon (final Component c, Graphics g, int x, int y) { if (imageIcon != null ) { imageIcon.paintIcon(c, g, x, y); } else { g.drawString("Loading album cover, please wait..." , x+300 , y+190 ); if (!retrieving) { retrieving = true ; retrievalThread = new Thread(new Runnable() { public void run () { try { setImageIcon(new ImageIcon(imageURL, "Album Cover" )); c.repaint(); } catch (Exception e) { e.printStackTrace(); } } }); retrievalThread.start(); } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.awt.*;import javax.swing.*;class ImageComponent extends JComponent { private static final long serialVersionUID = 1L ; 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); } }