分享

《Head First设计模式》阅读笔记.第十一章

 昵称465563 2010-10-27
1、代理(Proxy)模式部分

实现RMI(远程方法调用)的步骤:
引用
---------------------------------------------------------------
一、定义远程服务接口,扩展java.rmi.Remote。
二、实现远程服务具体类,继承java.rmi.UnicastRemoteObject类。
三、利用rmic生成Stub和Skeleton类,在JDK5.0中使用了动态代理,不需要生成任何类。
四、启动RMI注册表(rmiregistry)。
五、启动远程服务,即将远程服务具体类注册到RMI注册表中。
六、调用远程服务。
---------------------------------------------------------------


使用RMI常犯的三个错误:
引用
---------------------------------------------------------------
一、忘了在启动远程服务之前先启动RMI注册表(要用Naming.rebind()注册服务,rmiregistry必须是运行的)。
二、忘了将变量和返回值的类型转为可序列化的类型(这种错误无法在编译期发现,只会在运行时发现)。
三、忘了给客户端提供Stub类。
---------------------------------------------------------------


*transient关键字可以让JVM在序列化对象时忽略这个变量。

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

*使用代理模式创建代表(Representative)对象,让代表对象控制某对象的访问。被代理的对象可以是远程对象、创建开销大的对象或者需要安全控制的对象。

*远程代理是一般代理模式的一种实现。

代理模式有很多变种,几乎都与控制访问有关,它控制访问的几种方式:
引用
---------------------------------------------------------------
一、远程代理控制远程对象的访问。
二、虚拟代理控制创建开销大的资源的访问。
三、保护代理基于权限控制对资源的访问。
---------------------------------------------------------------


*远程代理(Remote Proxy)模式:可以作为另一个JVM上对象的本地代表。调用代理的方法会被代理利用网络转发到远程执行,并且结果会通过网络返回给代理,再由代理将结果转给客户。

*虚拟代理(Virtual Proxy)模式:作为创建开销大的对象的代表。虚拟代理经常在我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由代理来扮演它的替身。对象创建后,代理就会将请求直接委托给对象。

设计谜题
---------------------------------------------------------------
使用第十章的状态(State)模式对ImageProxy类进行重新设计。
---------------------------------------------------------------

*动态代理:Java在java.lang.reflect包中有自己的代理支持。利用这个包你可以在运行时动态地创建代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。因为实际的代理类是在运行时创建的,因此称这项Java技术为动态代理。

NonOwnerInvocationHandler代码:
Java代码 复制代码
  1. ---------------------------------------------------------------   
  2. import java.lang.reflect.*;   
  3.   
  4. public class NonOwnerInvocationHandler implements InvocationHandler {   
  5.   PersonBean person;   
  6.      
  7.   public NonOwnerInvocationHandler(PersonBean person){   
  8.     this.person = person;   
  9.   }   
  10.      
  11.   public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException{   
  12.     try{   
  13.       if(method.getName().startsWith("get")){   
  14.         return method.invoke(person,args);   
  15.       }else if(method.getName().equals("setHotOrNotRating")){   
  16.         return method.invoke(person,args);   
  17.       }else if(method.getName().startsWith("set")){   
  18.         throw new IllegalAccessException();   
  19.       }   
  20.     } catch (InvocationTargetException e){   
  21.       e.printStackTrace();   
  22.     }   
  23.     return null;   
  24.   }   
  25. }   
  26. ---------------------------------------------------------------  


Sharpen your pencil解答:
Java代码 复制代码
  1. ---------------------------------------------------------------   
  2. PersonBean getNonOwnerProxy(PersonBean person){   
  3.   return (PersonBean)Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),new NonOwnerInvocationHandler());   
  4. }   
  5.   
  6. PersonBean getProxy(PersonBean person,InvocationHandler handler){   
  7.   if(handler instanceof OwnerInvocationHandler){   
  8.     return getOwnerProxy(person);   
  9.   }else if(handler instanceof NonOwnerInvocationHandler){   
  10.     return getNonOwnerProxy(person);   
  11.   }   
  12. }   
  13. ---------------------------------------------------------------  


连连看解答:
引用
---------------------------------------------------------------
装饰者(Decorator)模式-->包装另一个对象,并提供额外的行为。
外观(Facade)模式-->包装许多对象以简化它们的接口。
代理(Proxy)模式-->包装另一个对象,并控制对它的访问。
适配器(Adapter)模式-->包装另一个对象,并提供不同的接口。
---------------------------------------------------------------


其他种类的代理:
引用
---------------------------------------------------------------
一、防火墙代理(Firewall Proxy):控制网络资源的访问,保护资源免受“坏客户”的侵害。
二、只能引用代理(Smart Reference Proxy):当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数。
三、缓存代理(Caching Proxy):为开销大的计算结果提供暂时存储。它允许多个客户共享结果以减少计算或网络延迟。
四、同步代理(Synchronization Proxy):在多线程的情况下为主题提供安全的访问。
五、复杂隐藏代理(Complexity Hiding Proxy):用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也成为外观代理(Facade Proxy)。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。
六、写入时复制代理(Copy-On-Write Proxy):用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止,这是虚拟代理的变体。
---------------------------------------------------------------


2、代理(Proxy)模式小结

*代理模式为另一个对象提供代表,以便控制客户对对象的访问,管理访问的方式有许多种。

*远程代理管理客户和远程对象之间的交互。

*虚拟代理控制访问实例化开销大的对象。

*保护模式基于调用者控制对对象方法的访问。

*代理模式有许多变体,例如:缓存代理、同步代理、防火墙代理与写入时复制代理。

*代理在结构上类似装饰者,但是目的不同。

*装饰者模式为对象加上行为,而代理控制访问。

*Java内置的代理支持,可以根据需要动态创建代理,并将所有调用分配到所选的处理器。

*和其它的包装者(wrapper)一样,代理会造成你的设计中类的数目的增加。

3、RMI(远程方法调用)实例
Java代码 复制代码
  1. /**  
  2.  * 远程接口  
  3.  *   
  4.  * @author zangweiren 2010-4-8  
  5.  *   
  6.  */  
  7. public interface HelloRemote extends Remote {   
  8.     String sayHello() throws RemoteException;   
  9. }   
  10.   
  11. /**  
  12.  * 远程服务实现类  
  13.  *   
  14.  * @author zangweiren 2010-4-8  
  15.  *   
  16.  */  
  17. public class HelloImpl extends UnicastRemoteObject implements HelloRemote {   
  18.   
  19.     private static final long serialVersionUID = -5554845400316615009L;   
  20.   
  21.     public static void main(String[] args) {   
  22.         try {   
  23.             HelloRemote helloRemote = new HelloImpl();   
  24.             Naming.rebind("HelloRemote", helloRemote);   
  25.         } catch (RemoteException e) {   
  26.             e.printStackTrace();   
  27.         } catch (MalformedURLException e) {   
  28.             e.printStackTrace();   
  29.         }   
  30.     }   
  31.   
  32.     public HelloImpl() throws RemoteException {   
  33.     }   
  34.   
  35.     @Override  
  36.     public String sayHello() throws RemoteException {   
  37.         return "Hello,world.I am zangweiren.";   
  38.     }   
  39. }   
  40.   
  41. /**  
  42.  * 远程服务客户端  
  43.  *   
  44.  * @author zangweiren 2010-4-8  
  45.  *   
  46.  */  
  47. public class HelloClient {   
  48.   
  49.     public static void main(String[] args) {   
  50.         try {   
  51.             HelloRemote helloRemote = (HelloRemote) Naming   
  52.                     .lookup("rmi://127.0.0.1/HelloRemote");   
  53.             String words = helloRemote.sayHello();   
  54.             System.out.println(words);   
  55.         } catch (MalformedURLException e) {   
  56.             e.printStackTrace();   
  57.         } catch (RemoteException e) {   
  58.             e.printStackTrace();   
  59.         } catch (NotBoundException e) {   
  60.             e.printStackTrace();   
  61.         }   
  62.     }   
  63.   
  64. }  


4、远程代理(Remote Proxy)模式实例

Java代码 复制代码
  1. /**  
  2.  * 服务器远程接口  
  3.  *   
  4.  * @author zangweiren 2010-4-8  
  5.  *   
  6.  */  
  7. public interface ServerRemote extends Remote {   
  8.     void shutdown() throws RemoteException;   
  9.   
  10.     void startup() throws RemoteException;   
  11. }   
  12.   
  13. /**  
  14.  * 服务器实现类  
  15.  *   
  16.  * @author zangweiren 2010-4-8  
  17.  *   
  18.  */  
  19. public class ServerImpl extends UnicastRemoteObject implements ServerRemote {   
  20.   
  21.     private static final long serialVersionUID = -1466325816915299894L;   
  22.   
  23.     public static void main(String[] args) {   
  24.         ServerRemote server;   
  25.         try {   
  26.             server = new ServerImpl();   
  27.             Naming.rebind("ServerRemote", server);   
  28.         } catch (RemoteException e) {   
  29.             e.printStackTrace();   
  30.         } catch (MalformedURLException e) {   
  31.             e.printStackTrace();   
  32.         }   
  33.     }   
  34.   
  35.     public ServerImpl() throws RemoteException {   
  36.     }   
  37.   
  38.     @Override  
  39.     public void shutdown() throws RemoteException {   
  40.         System.out.println("The server is shutdown.");   
  41.     }   
  42.   
  43.     @Override  
  44.     public void startup() throws RemoteException {   
  45.         System.out.println("The server is running...");   
  46.     }   
  47. }   
  48.   
  49. /**  
  50.  * 远程代理客户端测试程序  
  51.  *   
  52.  * @author zangweiren 2010-4-8  
  53.  *   
  54.  */  
  55. public class TestServer {   
  56.     public static void main(String[] args) {   
  57.         try {   
  58.             ServerRemote server = (ServerRemote) Naming.lookup("ServerRemote");   
  59.             server.startup();   
  60.             server.shutdown();   
  61.         } catch (MalformedURLException e) {   
  62.             e.printStackTrace();   
  63.         } catch (RemoteException e) {   
  64.             e.printStackTrace();   
  65.         } catch (NotBoundException e) {   
  66.             e.printStackTrace();   
  67.         }   
  68.     }   
  69. }  


测试结果:

引用
The server is running...
The server is shutdown.


5、虚拟代理(Virtual Proxy)模式实例(结合了状态模式)

Java代码 复制代码
  1. /**  
  2.  * 视频播放器  
  3.  *   
  4.  * @author zangweiren 2010-4-8  
  5.  *   
  6.  */  
  7. public interface MediaPlayer {   
  8.     int getHeight();   
  9.   
  10.     int getWidth();   
  11.   
  12.     void play();   
  13. }   
  14.   
  15. /**  
  16.  * 视频播放器实现类  
  17.  *   
  18.  * @author zangweiren 2010-4-8  
  19.  *   
  20.  */  
  21. public class MediaPlayerImpl implements MediaPlayer {   
  22.   
  23.     @Override  
  24.     public int getHeight() {   
  25.         return 1024;   
  26.     }   
  27.   
  28.     @Override  
  29.     public int getWidth() {   
  30.         return 768;   
  31.     }   
  32.   
  33.     @Override  
  34.     public void play() {   
  35.         System.out.println("The vedio is playing...");   
  36.     }   
  37.   
  38. }   
  39.   
  40. /**  
  41.  * 视频播放器状态  
  42.  *   
  43.  * @author zangweiren 2010-4-8  
  44.  *   
  45.  */  
  46. public interface MediaPlayerState extends MediaPlayer {   
  47.   
  48. }   
  49.   
  50. /**  
  51.  * 未加载状态  
  52.  *   
  53.  * @author zangweiren 2010-4-8  
  54.  *   
  55.  */  
  56. public class NotLoadedState implements MediaPlayerState {   
  57.     private MediaPlayerProxy player;   
  58.   
  59.     public NotLoadedState(MediaPlayerProxy player) {   
  60.         this.player = player;   
  61.     }   
  62.   
  63.     @Override  
  64.     public int getHeight() {   
  65.         return 800;   
  66.     }   
  67.   
  68.     @Override  
  69.     public int getWidth() {   
  70.         return 600;   
  71.     }   
  72.   
  73.     @Override  
  74.     public void play() {   
  75.         player.setState(player.getLoadingState());   
  76.         player.play();   
  77.     }   
  78.   
  79. }   
  80.   
  81. /**  
  82.  * 加载中状态  
  83.  *   
  84.  * @author zangweiren 2010-4-8  
  85.  *   
  86.  */  
  87. public class LoadingState implements MediaPlayerState {   
  88.   
  89.     private MediaPlayerProxy player;   
  90.   
  91.     public LoadingState(MediaPlayerProxy player) {   
  92.         this.player = player;   
  93.     }   
  94.   
  95.     @Override  
  96.     public int getHeight() {   
  97.         return 800;   
  98.     }   
  99.   
  100.     @Override  
  101.     public int getWidth() {   
  102.         return 600;   
  103.     }   
  104.   
  105.     @Override  
  106.     public void play() {   
  107.         for (int i = 0; i < 3; i++) {   
  108.             System.out.println("The video is loading,please wait...");   
  109.         }   
  110.         System.out.println("Video loaded.");   
  111.         player.setState(player.getLoadedState());   
  112.         player.play();   
  113.     }   
  114.   
  115. }   
  116.   
  117. /**  
  118.  * 已加载状态  
  119.  *   
  120.  * @author zangweiren 2010-4-8  
  121.  *   
  122.  */  
  123. public class LoadedState implements MediaPlayerState {   
  124.     private MediaPlayerProxy player;   
  125.   
  126.     public LoadedState(MediaPlayerProxy player) {   
  127.         this.player = player;   
  128.     }   
  129.   
  130.     @Override  
  131.     public int getHeight() {   
  132.         return 1024;   
  133.     }   
  134.   
  135.     @Override  
  136.     public int getWidth() {   
  137.         return 768;   
  138.     }   
  139.   
  140.     @Override  
  141.     public void play() {   
  142.         for (int i = 0; i < 5; i++) {   
  143.             System.out.println("The video is playing...Height:"  
  144.                     + player.getHeight() + ",Width:" + player.getWidth());   
  145.         }   
  146.         System.out.println("Finished.");   
  147.         player.setState(player.getNotLoadedState());   
  148.     }   
  149.   
  150. }   
  151.   
  152. /**  
  153.  * 视频播放器代理类  
  154.  *   
  155.  * @author zangweiren 2010-4-8  
  156.  *   
  157.  */  
  158. public class MediaPlayerProxy implements MediaPlayer {   
  159.     private MediaPlayerState notLoaded;   
  160.     private MediaPlayerState loading;   
  161.     private MediaPlayerState loaded;   
  162.     private MediaPlayerState state;   
  163.   
  164.     public MediaPlayerProxy() {   
  165.         notLoaded = new NotLoadedState(this);   
  166.         loading = new LoadingState(this);   
  167.         loaded = new LoadedState(this);   
  168.   
  169.         state = notLoaded;   
  170.     }   
  171.   
  172.     @Override  
  173.     public int getHeight() {   
  174.         return state.getHeight();   
  175.     }   
  176.   
  177.     public MediaPlayerState getLoadedState() {   
  178.         return loaded;   
  179.     }   
  180.   
  181.     public MediaPlayerState getLoadingState() {   
  182.         return loading;   
  183.     }   
  184.   
  185.     public MediaPlayerState getNotLoadedState() {   
  186.         return notLoaded;   
  187.     }   
  188.   
  189.     public MediaPlayerState getState() {   
  190.         return state;   
  191.     }   
  192.   
  193.     @Override  
  194.     public int getWidth() {   
  195.         return state.getWidth();   
  196.     }   
  197.   
  198.     @Override  
  199.     public void play() {   
  200.         state.play();   
  201.     }   
  202.   
  203.     public void setState(MediaPlayerState state) {   
  204.         this.state = state;   
  205.     }   
  206.   
  207. }   
  208.   
  209. 测试程序:   
  210. /**  
  211.  * 视频播放器测试程序  
  212.  *   
  213.  * @author zangweiren 2010-4-8  
  214.  *   
  215.  */  
  216. public class TestMediaPlayer {   
  217.   
  218.     public static void main(String[] args) {   
  219.         MediaPlayer player = new MediaPlayerProxy();   
  220.         System.out.println("Height:" + player.getHeight() + ",Width:"  
  221.                 + player.getWidth());   
  222.         player.play();   
  223.         System.out.println("Height:" + player.getHeight() + ",Width:"  
  224.                 + player.getWidth());   
  225.     }   
  226.   
  227. }  


测试结果:
引用
Height:800,Width:600
The video is loading,please wait...
The video is loading,please wait...
The video is loading,please wait...
Video loaded.
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
Finished.
Height:800,Width:600



6、保护代理(Protect Proxy)模式实例

Java代码 复制代码
  1. /**  
  2.  * 用户管理类接口  
  3.  *   
  4.  * @author zangweiren 2010-4-8  
  5.  *   
  6.  */  
  7. public interface UserManager {   
  8.   
  9.     public abstract void addUser(String name);   
  10.   
  11.     public abstract void deleteUser(String name);   
  12.   
  13.     public abstract void updateUser(String name,   
  14.             HashMap<String, String> properties);   
  15.   
  16. }   
  17.   
  18. /**  
  19.  * 用户管理类  
  20.  *   
  21.  * @author zangweiren 2010-4-8  
  22.  *   
  23.  */  
  24. public class UserManagerImpl implements UserManager {   
  25.     @Override  
  26.     public void addUser(String name) {   
  27.         System.out.println("User:" + name + " has been added.");   
  28.     }   
  29.   
  30.     @Override  
  31.     public void deleteUser(String name) {   
  32.         System.out.println("User:" + name + "has been deleted.");   
  33.     }   
  34.   
  35.     @Override  
  36.     public void updateUser(String name, HashMap<String, String> properties) {   
  37.         System.out.println("User:" + name + "has been updated.");   
  38.         System.out.println("Properties:");   
  39.         Iterator<String> keys = properties.keySet().iterator();   
  40.         String key;   
  41.         while (keys.hasNext()) {   
  42.             key = keys.next();   
  43.             System.out.println(key + "=" + properties.get(key));   
  44.         }   
  45.         System.out.println("--------------");   
  46.     }   
  47. }   
  48.   
  49. /**  
  50.  * 管理员处理类  
  51.  *   
  52.  * @author zangweiren 2010-4-8  
  53.  *   
  54.  */  
  55. public class AdminInvocationHandler implements InvocationHandler {   
  56.     private UserManager manager;   
  57.   
  58.     public AdminInvocationHandler(UserManager manager) {   
  59.         this.manager = manager;   
  60.     }   
  61.   
  62.     @Override  
  63.     public Object invoke(Object proxy, Method method, Object[] args)   
  64.             throws IllegalAccessException {   
  65.         try {   
  66.             if (method.getName().equals("addUser")) {   
  67.                 return method.invoke(manager, args);   
  68.             } else if (method.getName().equals("updateUser")) {   
  69.                 return method.invoke(manager, args);   
  70.             } else if (method.getName().equals("deleteUser")) {   
  71.                 return method.invoke(manager, args);   
  72.             }   
  73.         } catch (IllegalArgumentException e) {   
  74.             e.printStackTrace();   
  75.         } catch (InvocationTargetException e) {   
  76.             e.printStackTrace();   
  77.         }   
  78.         return null;   
  79.     }   
  80.   
  81. }   
  82.   
  83. /**  
  84.  * 普通用户处理类  
  85.  *   
  86.  * @author zangweiren 2010-4-8  
  87.  *   
  88.  */  
  89. public class UserInvocationHandler implements InvocationHandler {   
  90.     private UserManager manager;   
  91.   
  92.     public UserInvocationHandler(UserManager manager) {   
  93.         this.manager = manager;   
  94.     }   
  95.   
  96.     @Override  
  97.     public Object invoke(Object proxy, Method method, Object[] args)   
  98.             throws IllegalAccessException {   
  99.         try {   
  100.             if (method.getName().equals("addUser")) {   
  101.                 throw new IllegalAccessException();   
  102.             } else if (method.getName().equals("updateUser")) {   
  103.                 return method.invoke(manager, args);   
  104.             } else if (method.getName().equals("deleteUser")) {   
  105.                 throw new IllegalAccessException();   
  106.             }   
  107.         } catch (IllegalArgumentException e) {   
  108.             e.printStackTrace();   
  109.         } catch (InvocationTargetException e) {   
  110.             e.printStackTrace();   
  111.         }   
  112.         return null;   
  113.     }   
  114.   
  115. }   
  116.   
  117. /**  
  118.  * 工具类  
  119.  *   
  120.  * @author zangweiren 2010-4-8  
  121.  *   
  122.  */  
  123. public class UserManagerUtils {   
  124.     public static UserManager getAdminProxy(UserManager manager) {   
  125.         return (UserManager) Proxy.newProxyInstance(manager.getClass()   
  126.                 .getClassLoader(), manager.getClass().getInterfaces(),   
  127.                 new AdminInvocationHandler(manager));   
  128.     }   
  129.   
  130.     public static UserManager getUserProxy(UserManager manager) {   
  131.         return (UserManager) Proxy.newProxyInstance(manager.getClass()   
  132.                 .getClassLoader(), manager.getClass().getInterfaces(),   
  133.                 new UserInvocationHandler(manager));   
  134.     }   
  135. }   
  136.   
  137. /**  
  138.  * 测试类  
  139.  *   
  140.  * @author zangweiren 2010-4-8  
  141.  *   
  142.  */  
  143. public class TestUserManager {   
  144.   
  145.     public static void main(String[] args) {   
  146.         UserManager manager = new UserManagerImpl();   
  147.         UserManager admin = UserManagerUtils.getAdminProxy(manager);   
  148.         admin.addUser("Jim");   
  149.         HashMap<String, String> properties = new HashMap<String, String>();   
  150.         properties.put("Gender""male");   
  151.         properties.put("Age""28");   
  152.         admin.updateUser("Jim", properties);   
  153.         admin.deleteUser("Jim");   
  154.         System.out.println();   
  155.   
  156.         UserManager user = UserManagerUtils.getUserProxy(manager);   
  157.         try {   
  158.             user.addUser("Lily");   
  159.         } catch (Exception e) {   
  160.             System.out.println("Can't add User!");   
  161.         }   
  162.         properties = new HashMap<String, String>();   
  163.         properties.put("Gender""female");   
  164.         properties.put("Age""26");   
  165.         user.updateUser("Lily", properties);   
  166.         try {   
  167.             user.deleteUser("Lily");   
  168.         } catch (Exception e) {   
  169.             System.out.println("Can't delete User!");   
  170.         }   
  171.     }   
  172.   
  173. }  


测试结果:
引用
User:Jim has been added.
User:Jimhas been updated.
Properties:
Age=28
Gender=male
--------------
User:Jimhas been deleted.

Can't add User!
User:Lilyhas been updated.
Properties:
Age=26
Gender=female
--------------
Can't delete User!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多