Proxy Pattern 代理模式

本文介绍了Java中的代理模式,包括远程代理RMI的基本步骤,以及代理模式在控制远程对象访问、资源昂贵创建、权限控制等方面的应用。虚拟代理用于延迟对象创建,保护代理用于控制访问权限。此外,还提到了Java动态代理实现,以及防火墙代理、智能引用代理、缓存代理、同步代理和复杂度隐藏代理等代理变种。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RMI:

1. Create a remote interface, which provides a set of methods that can be called remotely.

2. Make sure all arguments and return type in the interface are serializable.

3. You can declare transient variable so it will not be serialized.


Proxy Pattern: provides a surrogate or placeholder for another object to control access to it. 

Use the proxy pattern to create a representation object that control access to another object, which may be remote, expensive to create or in need of securing.

A remote proxy controls access to a remote object.

A virtual proxy controls access to a resource that is expensive to create.

A protection proxy controls access to a resource based on access rights.


Virtual Proxy:

The virtual proxy often defers the creation of the object until it is needed; the Virtual Proxy also acts as a surrogate for the object before and while it is being created. After that, the proxy delegates requests directly to the Real Object.

虚拟代理:在对象创建时添加行为。Proxy里含有这个对象,当调用Proxy时,这个对象才被创建。


定义代理:

public class ImageProxy implements Icon {
	ImageIcon imageIcon;
	URL imageURL;
	Thread retrieveThread;
	boolean retrieving = false;

	public ImageProxy(URL url) {
		imageURL = url;
	}

	@Override
	public int getIconHeight() {
		if (imageIcon != null) {
			return imageIcon.getIconHeight();
		} else {
			return 600;
		}
	}

	@Override
	public int getIconWidth() {
		if (imageIcon != null) {
			return imageIcon.getIconWidth();
		} else {
			return 600;
		}
	}

	@Override
	public void paintIcon(Component c, Graphics g, int x, int y) {
		if (imageIcon != null) {
			imageIcon.paintIcon(c, g, x, y);
		} else {
			g.drawString("Downloading image...", x + 300, y + 300);
			if (!retrieving) {
				retrieving = true;
				retrieveThread = new Thread(new Runnable() {
					@Override
					public void run() {
						imageIcon = new ImageIcon(imageURL, "image");
						c.repaint();
					}
				});
				retrieveThread.start();
			}
		}
	}
}
定义Client:

public class ImageProxyTestDrive {
	JFrame frame = new JFrame("Image Proxy");
	ImageComponent image;
	JMenuBar menuBar;
	JMenu menu;
	Hashtable<String, URL> images = new Hashtable<String, URL>();

	public static void main(String[] args) throws Exception {
		ImageProxyTestDrive test = new ImageProxyTestDrive();
	}

	public ImageProxyTestDrive() throws Exception {
		images.put(
				"Image1",
				new URL(
						"http://stuffpoint.com/nature/image/24701-nature-natural-beauty.jpg"));
		images.put(
				"Images2",
				new URL(
						"http://stuffpoint.com/nature/image/43316-nature-gorgeous-waterfall-wallpaper.jpg"));
		images.put("Images3", new URL(
				"http://stuffpoint.com/nature/image/58924-nature-paradise.jpg"));

		Icon icon = new ImageProxy(images.get("Image1"));
		image = new ImageComponent(icon);
		
		menu = new JMenu("Menu");
		for (Enumeration<String> e = images.keys(); e.hasMoreElements();) {
			JMenuItem menuItem = new JMenuItem(e.nextElement());
			menuItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					image.setIcon(new ImageProxy(images.get(e
							.getActionCommand())));
					frame.repaint();
				}

			});
			menu.add(menuItem);
		}
		menuBar = new JMenuBar();
		menuBar.add(menu);
		
		frame.setJMenuBar(menuBar);
		frame.getContentPane().add(image);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(800, 600);
		frame.setVisible(true);
	}
}

class ImageComponent extends JComponent {
	private static final long serialVersionUID = 2034018324585301738L;
	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);
	}
}
上例中当菜单项被点击后,下载图片并显示。图片加载前显示文字,另开线程下载,下载完成后显示图片。

应用:load图片(先显示loading...,加载完再显示图片)。


Protection Proxy:

In java.lang.reflect package, Java lets you creates a proxy class on the fly that implements one or more interfaces and forwards method invocations to a class that you specify. Because the actual proxy class is created at runtime, we refer to this Java technology as a dynamic proxy. 

Protection Proxy consists two classes: Proxy and InvocationHandler. 

InvocationHandler gets passed all method calls that are invoked on the Proxy, which controls access to the methods of the Real Object. The job of InvocationHandler is to respond to any method calls on the Proxy.

保护代理用来控制对象方法的访问权限。调用对象方法时,不是直接引用对象访问,而是在其代理上调用,由代理控制访问权限。保护代理有两部分组成,一是代理,二是调用处理。代理由java自动生成,在代理上调用方法时,会根据调用处理里的代码执行。

定义Real Object:

public interface PersonBean {
	String getName();
	String getGender();
	String getInterests();
	int getHotOrNotRating();
	
	void setName(String name);
	void setGender(String gender);
	void setInterests(String interests);
	void setHotOrNotRating(int rating);
}
public class PersonBeanImpl implements PersonBean {
	String name;
	String gender;
	String interests;
	int rating;
	int ratingCount = 0;

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String getGender() {
		return gender;
	}

	@Override
	public String getInterests() {
		return interests;
	}

	@Override
	public int getHotOrNotRating() {
		return (ratingCount == 0 ? 0 : rating / ratingCount);
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public void setGender(String gender) {
		this.gender = gender;
	}

	@Override
	public void setInterests(String interests) {
		this.interests = interests;
	}

	@Override
	public void setHotOrNotRating(int rating) {
		this.rating += rating;
		ratingCount++;
	}
}

定义Invocation Handler:

import java.lang.reflect.*;
public class OwnerInvocationHandler implements InvocationHandler {
	PersonBean person;
	public OwnerInvocationHandler(PersonBean person) {
		this.person = person;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
			if(method.getName().startsWith("get")) {
				return method.invoke(person, args);
			} else if(method.getName().equals("setHotOrNotRating")) {
				throw new IllegalAccessException();
			} else if(method.getName().startsWith("set")) {
				return method.invoke(person, args);
			}
		return null;
	}
}
import java.lang.reflect.*;
public class NonOwnerInvocationHandler implements InvocationHandler {
	PersonBean person;

	public NonOwnerInvocationHandler(PersonBean person) {
		this.person = person;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		if (method.getName().startsWith("get")) {
			return method.invoke(person, args);
		} else if (method.getName().equals("setHotOrNotRating")) {
			return method.invoke(person, args);
		} else if (method.getName().startsWith("set")) {
			throw new IllegalAccessException();
		}
		return null;
	}
}
定义Client:

import java.lang.reflect.Proxy;
public class MatchMakingTestDrive {
	public static void main(String[] args) {
		MatchMakingTestDrive test = new MatchMakingTestDrive();
		test.drive();
		
	}
	public void drive() {
		PersonBean joe = new PersonBeanImpl();
		joe.setName("Joe");
		joe.setGender("male");

		PersonBean ownerProxy = getOwnerProxy(joe);
		System.out.println("Name is " + ownerProxy.getName());
		ownerProxy.setInterests("Badminton");
		System.out.println("Interest set to " + ownerProxy.getInterests());

		try {
			ownerProxy.setHotOrNotRating(10);
		} catch (Exception e) {
			System.out.println("Can't set rating from owner proxy");
		}
		System.out.println("Rating is " + ownerProxy.getHotOrNotRating());
	}
	
	PersonBean getOwnerProxy(PersonBean person) {
		return (PersonBean) Proxy.newProxyInstance(person.getClass()
				.getClassLoader(), person.getClass().getInterfaces(),
				new OwnerInvocationHandler(person));
	}

	PersonBean getNonOwnerProxy(PersonBean person) {
		return (PersonBean) Proxy.newProxyInstance(person.getClass()
				.getClassLoader(), person.getClass().getInterfaces(),
				new NonOwnerInvocationHandler(person));
	}
}
在上面例子中,一个PersonBean对象有两个Proxy,一个是以PersonBean的拥有者身份使用的Proxy,一个是以PersonBean的非拥有者身份使用的Proxy。两个Proxy对PersonBean中方法的访问权限不同。当越权访问时,会产生异常。
应用:用户访问权限

Proxy Variants:

Firewall Proxy: controls access to a set of network resources, protecting the subject from "bad" clients.

Smart Reference Proxy: provides additional actions whenever a subject is referenced, such as counting the number of references to an object.

Caching Proxy: provides temporary storage for results of operations that are expensive. It can also allow multiple clients to share the results to reduce computation or network latency. 

Synchronization Proxy: provides safe access to a subject from multiple threads.

Complexity Hiding Proxy: hides the complexity of and controls access to a complex set of classes. This is sometimes called Facade Proxy. Facade Pattern provides an alternative interface, but Facade Proxy controls access.

Copy-On-Write Proxy: controls the copying of an object by deferring the copying of an object until it is required by a client. This is a variant of the Virtual Proxy.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值