Proxy Pattern 代理模式

原创 2015年07月07日 13:31:59

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.

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

代理模式【Proxy Pattern】

什么是代理模式呢?我很忙,忙的没空理你,那你要找我呢就先找我的代理人吧,那代理人总要知道 被代理人能做哪些事情不能做哪些事情吧,那就是两个人具备同一个接口,代理人虽然不能干活,但是被 代理的人能干...

java代理模式(Proxy Pattern)

场景中秋假期到了,李敏要到火车站买张回家的车票,发现去趟车站太远了,于是选择学校附近的票务中心,让票务中心的工作人员帮自己买票。具体分析在上面的例子中,“买票”是业务操作,票务中心帮忙买票,那么“票务...
  • onpwerb
  • onpwerb
  • 2016年09月09日 18:32
  • 296

代理模式(Proxy Pattern)

《设计模式的艺术》 刘伟 著 读书笔记 静态代理由于某些原因,客户端不能或不像直接访问某个对象,此时可以通过一个称之为“代理”的第三者来实现间接访问,这种设计模式就是代理模式。代理模式:给某一个...

第13章 代理模式(Proxy Pattern)

代理模式(Proxy Pattern) ——.NET设计模式系列之十四 Terrylee,2006年5月 摘要:在软件系统中,有些对象有时候由于跨越网络或者其他的障碍,而不能够或者不想直接访问另...

代理模式(Proxy Pattern)。

博文中的内容来源《设计模式之禅》这一本书,感激不尽。

代理模式 Proxy Pattern

代理模式 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。 介绍 意...

代理模式(Proxy Pattern)

使用简单的对象来代替一个复杂的对象或者为另一个对象提供一个占位符来控制对它的访问。经典UML类如下:      使用场合和优势:  实时或是在内存中创建一个对象代价太高的情况下。 延迟创建直到...

代理模式(Proxy Pattern)

代理模式(Proxy Pattern)定义:对其他对象提供一种代理以控制对这个对象的访问。 代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。代理模式经常在以...

(C++实现)——代理模式(Proxy Pattern)

概述 作为C++工程师,免不了要管理内存,内存管理也是C++中的难点,而智能指针采用引用计数的办法很方便的帮我们管理了内存的使用,极大方便了我们的工作效率。而智能指针的这种用法其实就是代...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Proxy Pattern 代理模式
举报原因:
原因补充:

(最多只允许输入30个字)