`
up2pu
  • 浏览: 218399 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

设计模式读书笔记-1代理模式Proxy(1)

阅读更多
1.定义
    为其他对象提供一种代理以控制对这个对象的访问。
2.类图
   
3.比较
  3.1动态代理和静态代理
    静态代理实现的时候,在Subject接口上定义很多的方法,代理类里面自然也要实现很多方法。
    动态代理实现的时候,虽然Subject接口上定义了很多方法,但是动态代理类始终只有一个invoke方法。这样,当Subject接口发生变化的时候,动态代理的接口就不需要跟着变化了。

  3.2代理模式与适配器模式
    相似性:它们都为一个对象提供间接性的访问,而且都是从自身以外的一个接口向这个对象转发请求。
    不同性:功能上,两个模式是不一样的。适配器模式主要用来解决接口之间不匹配的问题,它通常是为所适配的对象提供一个不同的接口;而代理模式会实现和目标对象相同的接口。

  3.3代理模式与装饰模式
    相似性:在实现上相似,都是在转调其他对象的前后执行一定的功能。
    不同性:目的与功能不一样。装饰模式的目的是为了让你不声称子类就可以给对象添加职责,也就是说为了动态的增加功能。而代理模式的主要目的是控制对对象的访问。

4.应用
  4.1远程代理
      4.1.1 rmi基础
        a.创建远程接口
package net.ecoolsoft.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface MyRemote extends Remote {
	public String sayHello() throws RemoteException;
}


        b.创建远程实现
package net.ecoolsoft.rmi;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
 * 通过该文件生成MyRemoteImpl_Stub.class
 * DesignPattern\bin>rmic net.ecoolsoft.rmi.MyRemoteImpl
 */
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {

	protected MyRemoteImpl() throws RemoteException {
		super();
	}

	public String sayHello() throws RemoteException {
		return "Server says, 'Hey'";
	}

	public static void main(String[] args) {
		try {
			MyRemote service = new MyRemoteImpl();
			Naming.rebind("RemoteHello", service);
		} catch(Exception ex) {
			ex.printStackTrace();
		}
	}
	
}

        c.使用rmic生成stub
rmic有很多参数,其中-keep是生成java代码
DesignPattern\bin>rmic net.ecoolsoft.rmi.MyRemoteImpl -keep
        d.启动RMI registry
DesignPattern\bin>rmiregistry
需要在stub所在类路径上运行,否则会报以下错误:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: net.ecoolsoft.rmi.MyRemoteImpl_Stub
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:385)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
	at sun.rmi.transport.Transport$1.run(Transport.java:153)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
	at java.lang.Thread.run(Thread.java:595)
	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247)
	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223)
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:343)
	at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
	at java.rmi.Naming.rebind(Naming.java:160)
	at net.ecoolsoft.rmi.MyRemoteImpl.main(MyRemoteImpl.java:26)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: net.ecoolsoft.rmi.MyRemoteImpl_Stub
	at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:375)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
	at sun.rmi.transport.Transport$1.run(Transport.java:153)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
	at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.ClassNotFoundException: net.ecoolsoft.rmi.MyRemoteImpl_Stub
	at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:242)
	at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:430)
	at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
	at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
	at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
	at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1544)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1466)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1699)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
	... 9 more

        e.启动远程服务
DesignPattern\bin>java net.ecoolsoft.rmi.MyRemoteImpl
        f.启动客户端测试
DesignPattern\bin>java net.ecoolsoft.rmi.MyRemoteClient
package net.ecoolsoft.rmi;
import java.rmi.Naming;
public class MyRemoteClient {
	public static void main(String[] args) {
		new MyRemoteClient().go();
	}
	public void go() {
		try {
			MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/RemoteHello");
			String s = service.sayHello();
			System.out.println(s);
		} catch(Exception ex) {
			ex.printStackTrace();
		}
	}
}

      4.1.2 远程代理实例
     
        a.GumballMachineRemote
package headfirst.proxy.gumball;
import java.rmi.*;
public interface GumballMachineRemote extends Remote {
	public int getCount() throws RemoteException;
	public String getLocation() throws RemoteException;
	public State getState() throws RemoteException;
}

        b.GumballMachine
package headfirst.proxy.gumball;
import java.rmi.*;
import java.rmi.server.*;
public class GumballMachine
		extends UnicastRemoteObject implements GumballMachineRemote 
{
	State soldOutState;
	State noQuarterState;
	State hasQuarterState;
	State soldState;
	State winnerState;
	State state = soldOutState;
	int count = 0;
 	String location;
	public GumballMachine(String location, int numberGumballs) throws RemoteException {
		soldOutState = new SoldOutState(this);
		noQuarterState = new NoQuarterState(this);
		hasQuarterState = new HasQuarterState(this);
		soldState = new SoldState(this);
		winnerState = new WinnerState(this);
		this.count = numberGumballs;
 		if (numberGumballs > 0) {
			state = noQuarterState;
		} 
		this.location = location;
	}
	public void insertQuarter() {
		state.insertQuarter();
	}
	public void ejectQuarter() {
		state.ejectQuarter();
	}
	public void turnCrank() {
		state.turnCrank();
		state.dispense();
	}
	void setState(State state) {
		this.state = state;
	}
	void releaseBall() {
		System.out.println("A gumball comes rolling out the slot...");
		if (count != 0) {
			count = count - 1;
		}
	}
	public void refill(int count) {
		this.count = count;
		state = noQuarterState;
	}
	public int getCount() {
		return count;
	}
    public State getState() {
        return state;
    }
    public String getLocation() {
        return location;
    }
    public State getSoldOutState() {
        return soldOutState;
    }
    public State getNoQuarterState() {
        return noQuarterState;
    }
    public State getHasQuarterState() {
        return hasQuarterState;
    }
    public State getSoldState() {
        return soldState;
    }
    public State getWinnerState() {
        return winnerState;
    }
	public String toString() {
		StringBuffer result = new StringBuffer();
		result.append("\nMighty Gumball, Inc.");
		result.append("\nJava-enabled Standing Gumball Model #2004");
		result.append("\nInventory: " + count + " gumball");
		if (count != 1) {
			result.append("s");
		}
		result.append("\n");
		result.append("Machine is " + state + "\n");
		return result.toString();
	}
}

        c.GumballMachineTestDrive
package headfirst.proxy.gumball;
import java.rmi.*;
public class GumballMachineTestDrive {
	public static void main(String[] args) {
		GumballMachineRemote gumballMachine = null;
		int count;
		if (args.length < 2) {
			System.out.println("GumballMachine <name> <inventory>");
 			System.exit(1);
		}
		try {
			count = Integer.parseInt(args[1]);
			gumballMachine = 
				new GumballMachine(args[0], count);
			Naming.rebind("//" + args[0] + "/gumballmachine", gumballMachine);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

        d.GumballMonitor
package headfirst.proxy.gumball;
import java.rmi.*;
public class GumballMonitor {
	GumballMachineRemote machine;
	public GumballMonitor(GumballMachineRemote machine) {
		this.machine = machine;
	}
	public void report() {
		try {
			System.out.println("Gumball Machine: " + machine.getLocation());
			System.out.println("Current inventory: " + machine.getCount() + " gumballs");
			System.out.println("Current state: " + machine.getState());
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
}

        e.GumballMonitorTestDrive
package headfirst.proxy.gumball;
import java.rmi.*;
public class GumballMonitorTestDrive {
	public static void main(String[] args) {
		String[] location = {"rmi://santafe.mightygumball.com/gumballmachine",		                     "rmi://boulder.mightygumball.com/gumballmachine",		                     "rmi://seattle.mightygumball.com/gumballmachine"}; 
		if (args.length >= 0)
        {
            location = new String[1];
            location[0] = "rmi://" + args[0] + "/gumballmachine";
        }
		GumballMonitor[] monitor = new GumballMonitor[location.length];	
		for (int i=0;i < location.length; i++) {
			try {
           		GumballMachineRemote machine = 
						(GumballMachineRemote) Naming.lookup(location[i]);
           		monitor[i] = new GumballMonitor(machine);
				System.out.println(monitor[i]);
        	} catch (Exception e) {
            	e.printStackTrace();
        	}
		}
		for(int i=0; i < monitor.length; i++) {
			monitor[i].report();
		}
	}
}

        f.执行过程
HeadFirstDesignPatterns_code102507\HF_DP\bin>rmiregistry
java GumballMachineTestDrive localhost 100
java GumballMonitorTestDrive localhost

  4.2虚拟代理

a.ImageComponent
package headfirst.proxy.virtualproxy;
import java.awt.*;
import javax.swing.*;
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);
	}
}

b.ImageProxy
package headfirst.proxy.virtualproxy;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ImageProxy implements Icon {
	ImageIcon imageIcon;
	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;
		}
	}
	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 CD cover, please wait...", x+300, y+190);
			if (!retrieving) {
				retrieving = true;

				retrievalThread = new Thread(new Runnable() {
					public void run() {
						try {
							imageIcon = new ImageIcon(imageURL, "CD Cover");
							c.repaint();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				});
				retrievalThread.start();
			}
		}
	}
}

c.ImageProxyTestDrive
package headfirst.proxy.virtualproxy;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class ImageProxyTestDrive {
	ImageComponent imageComponent;
	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://images.amazon.com/images/P/B000003S2K.01.LZZZZZZZ.jpg");
        cds.put("Buddha Bar","http://images.amazon.com/images/P/B00009XBYK.01.LZZZZZZZ.jpg");       cds.put("Ima","http://images.amazon.com/images/P/B000005IRM.01.LZZZZZZZ.jpg");     cds.put("Karma","http://images.amazon.com/images/P/B000005DCB.01.LZZZZZZZ.gif");
        cds.put("MCMXC A.D.","http://images.amazon.com/images/P/B000002URV.01.LZZZZZZZ.jpg");
        cds.put("Northern Exposure","http://images.amazon.com/images/P/B000003SFN.01.LZZZZZZZ.jpg");
        cds.put("Selected Ambient Works, Vol. 2","http://images.amazon.com/images/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) {
           		     imageComponent.setIcon(new ImageProxy(getCDUrl(event.getActionCommand())));
					frame.repaint();
           	      }
        	});
		}
		// set up frame and menus
		Icon icon = new ImageProxy(initialURL);
		imageComponent = new ImageComponent(icon);
		frame.getContentPane().add(imageComponent);
		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;
		}
	}
}

d.公司内网使用代理(VM arguments)
-DproxySet=true -DproxyHost=host -DproxyPort=port
  4.3安全代理

a.PersonBean
package headfirst.proxy.javaproxy;
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); 
}

b.PersonBeanImpl
package headfirst.proxy.javaproxy;
public class PersonBeanImpl implements PersonBean {
	String name;
	String gender;
	String interests;
	int rating;
	int ratingCount = 0;
	public String getName() {
		return name;	
	} 
	public String getGender() {
		return gender;
	}
	public String getInterests() {
		return interests;
	}
	public int getHotOrNotRating() {
		if (ratingCount == 0) return 0;
		return (rating/ratingCount);
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setGender(String gender) {
		this.gender = gender;
	} 
	public void setInterests(String interests) {
		this.interests = interests;
	} 
	public void setHotOrNotRating(int rating) {
		this.rating += rating;	
		ratingCount++;
	}
}

c.OwnerInvocationHandler
package headfirst.proxy.javaproxy;
import java.lang.reflect.*;
public class OwnerInvocationHandler implements InvocationHandler { 
	PersonBean person;
	public OwnerInvocationHandler(PersonBean person) {
		this.person = person;
	}
	public Object invoke(Object proxy, Method method, Object[] args) 
			throws IllegalAccessException {
		try {
			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);
			} 
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } 
		return null;
	}
}

d.NonOwnerInvocationHandler
package headfirst.proxy.javaproxy;
import java.lang.reflect.*;
public class NonOwnerInvocationHandler implements InvocationHandler { 
	PersonBean person;
	public NonOwnerInvocationHandler(PersonBean person) {
		this.person = person;
	}
	public Object invoke(Object proxy, Method method, Object[] args) 
			throws IllegalAccessException {
		try {
			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();
			} 
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } 
		return null;
	}
}

e.MatchMakingTestDrive
package headfirst.proxy.javaproxy;
import java.lang.reflect.*;
import java.util.*;
public class MatchMakingTestDrive {
	Hashtable datingDB = new Hashtable();
	public static void main(String[] args) {
		MatchMakingTestDrive test = new MatchMakingTestDrive();
		test.drive();
	}
	public MatchMakingTestDrive() {
		initializeDatabase();
	}
	public void drive() {
		PersonBean joe = getPersonFromDatabase("Joe Javabean"); 
		PersonBean ownerProxy = getOwnerProxy(joe);
		System.out.println("Name is " + ownerProxy.getName());
		ownerProxy.setInterests("bowling, Go");
		System.out.println("Interests set from owner proxy");
		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 nonOwnerProxy = getNonOwnerProxy(joe);
		System.out.println("Name is " + nonOwnerProxy.getName());
		try {
			nonOwnerProxy.setInterests("bowling, Go");
		} catch (Exception e) {
			System.out.println("Can't set interests from non owner proxy");
		}
		nonOwnerProxy.setHotOrNotRating(3);
		System.out.println("Rating set from non owner proxy");
		System.out.println("Rating is " + nonOwnerProxy.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 getPersonFromDatabase(String name) {
		return (PersonBean)datingDB.get(name);
	}
	void initializeDatabase() {
		PersonBean joe = new PersonBeanImpl();
		joe.setName("Joe Javabean");
		joe.setInterests("cars, computers, music");
		joe.setHotOrNotRating(7);
		datingDB.put(joe.getName(), joe);

		PersonBean kelly = new PersonBeanImpl();
		kelly.setName("Kelly Klosure");
		kelly.setInterests("ebay, movies, music");
		kelly.setHotOrNotRating(6);
		datingDB.put(kelly.getName(), kelly);
	}
}


5.参考资料
《Head First Design Pattern》
《大话设计模式》



   
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics