设计模式学习--代理模式

概述

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


OO原则

———————————————————————————————————————————————————
  • 封装变化
  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程
  • 为交互对象之间的松耦合设计而努力
  • 类应该对扩展开放,对修改关闭
  • 依赖抽象,不要以来具体类
  • 只和朋友交谈
  • 别找我,我会找你
  • 类应该只有一个改变的理由


要点

———————————————————————————————————————————————————

  • 代理模式为另一个对象提供代表,以便控制客户对对象访问,管理访问的方式有许多种。
  • 远程代理管理客户和远程对象之间的交互。
  • 虚拟代理控制访问实例化开销大的对象。
  • 保护代理基于调用者控制对象方法的访问。
  • 代理模式有许多变体,例如:缓存代理、同步代理、防火墙代理和写入时复制代理。
  • 代理在结构上类似装饰者,但是目的不同。
  • 装饰者模式为对象加上行为,而代理是控制访问。
  • Java内置的代理支持,可以根据需要建立动态代理,并将所有调用分配到所选的处理器。
  • 就和其他的包装者(wrapper)一样,代理会造成你的设计中类的数目增加。

例子:实现可以远程控制的糖果机

———————————————————————————————————————————————————
代码的改变可以对照“状态模式”那一篇博客

代理模式并不是那么容易理解,需要好好介绍一下

远程代理的角色
远程代理就好比“远程对象的本地代表”。何谓“远程对象”?这是一种对象,活在不同的Java虚拟机堆中(更一般的说法为,在不同的地址空间运行的远程对象)。何谓“本地代表”?这是一种可以由本地方法调用的对象,其行为会转发到远程对象中。


简单来说,代理就是一个本地对象,是客户直接打交道的对象,然而这个本地对象再跟真正的远程对象进行沟通,远程对象把请求的结果返回给代理,再由代理把结果返回给客户。这是远程控制的整个流程。


在本例子当中,糖果机充当的角色是真正的远程对象,是代理服务的对象。而代理呢,是要通过监视器从远程服务器中注册返回得到的。这里涉及到Java的RMI(远程方法调用),不是设计模式的内容,不多说。
我们要知道的就是,代理对象是通过RMI Registry得到的,它叫做stub(桩),stub扮演的是客户辅助对象,实在客户堆里的;然而在Java RMI中在服务器堆中skeleton(骨架)作为服务辅助对象。


不知道大家能不能看明白,其实在《Head First设计模式》当中,讲解得非常详细了,图文并茂,看几遍应该就能理解远程代理的操作流程是怎样的了。

来看看糖果机的远程代理实现吧
客户端里有:
GumballMonitor:这是我们的监视器代码,它使用代理来和远程糖果机沟通。
GumballStub:这是我们的代理
服务器端有:
GumballSkeleton:这是我们的服务器辅助对象
GumballMachine:这是我们的服务对象,它为客户暴露一个远程接口以供使用。

让GumballMachine准备好当一个远程服务
GumabllMachineRemote接口

[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. import java.rmi.Remote;  
  4. import java.rmi.RemoteException;  
  5.   
  6. /** 
  7.  * 让GumballMachine准备好当一个远程服务 
  8.  * 代理模式的使用例子 
  9.  */  
  10. public interface GumballMachineRemote extends Remote {  
  11.     public int getCount() throws RemoteException;  
  12.     public String getLocation() throws RemoteException;  
  13.     public State getState() throws RemoteException;  
  14. }  


修改状态接口
[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. import java.io.*;  
  4.   
  5. /** 
  6.  * 扩展Serializable接口,则State的所有子类就可以在网络上传送了 
  7.  */  
  8. public interface State extends Serializable {  
  9.    
  10.     public void insertQuarter();  
  11.     public void ejectQuarter();  
  12.     public void turnCrank();  
  13.     public void dispense();  
  14. }  

修改状态实现类
[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. public class NoQuarterState implements State {  
  4.     //对于State的每个实现,我们都在GumballMachine实例变量前面加上transient关键字,这就就告诉JVM不要序列化这个字段  
  5.     transient GumballMachine gumballMachine;  
  6.    
  7.     public NoQuarterState(GumballMachine gumballMachine) {  
  8.         this.gumballMachine = gumballMachine;  
  9.     }  
  10.    
  11.     public void insertQuarter() {  
  12.         System.out.println("You inserted a quarter");  
  13.         gumballMachine.setState(gumballMachine.getHasQuarterState());  
  14.     }  
  15.    
  16.     public void ejectQuarter() {  
  17.         System.out.println("You haven't inserted a quarter");  
  18.     }  
  19.    
  20.     public void turnCrank() {  
  21.         System.out.println("You turned, but there's no quarter");  
  22.      }  
  23.    
  24.     public void dispense() {  
  25.         System.out.println("You need to pay first");  
  26.     }   
  27.    
  28.     public String toString() {  
  29.         return "waiting for quarter";  
  30.     }  
  31. }  


HasQuarterState.java
[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. import java.util.Random;  
  4.   
  5. public class HasQuarterState implements State {  
  6.     Random randomWinner = new Random(System.currentTimeMillis());   //随机数产生器  
  7.     transient GumballMachine gumballMachine;  
  8.    
  9.     public HasQuarterState(GumballMachine gumballMachine) {  
  10.         this.gumballMachine = gumballMachine;  
  11.     }  
  12.     
  13.     public void insertQuarter() {  
  14.         System.out.println("You can't insert another quarter");  
  15.     }  
  16.    
  17.     public void ejectQuarter() {  
  18.         System.out.println("Quarter returned");  
  19.         gumballMachine.setState(gumballMachine.getNoQuarterState());  
  20.     }  
  21.    
  22.     public void turnCrank() {  
  23.         System.out.println("You turned...");  
  24.         int winner = randomWinner.nextInt(10);  //参数0~10的随机数  
  25.         if((winner == 0) && (gumballMachine.getCount() > 1)) {   //如果随机树为0,且足够的糖果的话,则可以得到两颗糖果  
  26.             gumballMachine.setState(gumballMachine.getWinnerState());  
  27.         } else {  
  28.             gumballMachine.setState(gumballMachine.getSoldState());  
  29.         }  
  30.     }  
  31.   
  32.     public void dispense() {  
  33.         System.out.println("No gumball dispensed");  
  34.     }  
  35.    
  36.     public String toString() {  
  37.         return "waiting for turn of crank";  
  38.     }  
  39. }  

SoldOutState.java
[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. public class SoldOutState implements State {  
  4.     transient GumballMachine gumballMachine;  
  5.    
  6.     public SoldOutState(GumballMachine gumballMachine) {  
  7.         this.gumballMachine = gumballMachine;  
  8.     }  
  9.    
  10.     public void insertQuarter() {  
  11.         System.out.println("You can't insert a quarter, the machine is sold out");  
  12.     }  
  13.    
  14.     public void ejectQuarter() {  
  15.         System.out.println("You can't eject, you haven't inserted a quarter yet");  
  16.     }  
  17.    
  18.     public void turnCrank() {  
  19.         System.out.println("You turned, but there are no gumballs");  
  20.     }  
  21.    
  22.     public void dispense() {  
  23.         System.out.println("No gumball dispensed");  
  24.     }  
  25.    
  26.     public String toString() {  
  27.         return "sold out";  
  28.     }  
  29. }  

SoldState.java
[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. public class SoldState implements State {  
  4.    
  5.     transient GumballMachine gumballMachine;  
  6.    
  7.     public SoldState(GumballMachine gumballMachine) {  
  8.         this.gumballMachine = gumballMachine;  
  9.     }  
  10.          
  11.     public void insertQuarter() {  
  12.         System.out.println("Please wait, we're already giving you a gumball");  
  13.     }  
  14.    
  15.     public void ejectQuarter() {  
  16.         System.out.println("Sorry, you already turned the crank");  
  17.     }  
  18.    
  19.     public void turnCrank() {  
  20.         System.out.println("Turning twice doesn't get you another gumball!");  
  21.     }  
  22.    
  23.     public void dispense() {  
  24.         gumballMachine.releaseBall();  
  25.         if (gumballMachine.getCount() > 0) {  
  26.             gumballMachine.setState(gumballMachine.getNoQuarterState());  
  27.         } else {  
  28.             System.out.println("Oops, out of gumballs!");  
  29.             gumballMachine.setState(gumballMachine.getSoldOutState());  
  30.         }  
  31.     }  
  32.    
  33.     public String toString() {  
  34.         return "dispensing a gumball";  
  35.     }  
  36. }  


WinnerState.java
[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. public class WinnerState implements State {  
  4.     transient GumballMachine gumballMachine;  
  5.    
  6.     public WinnerState(GumballMachine gumballMachine) {  
  7.         this.gumballMachine = gumballMachine;  
  8.     }  
  9.    
  10.     public void insertQuarter() {  
  11.         System.out.println("Please wait, we're already giving you a Gumball");  
  12.     }  
  13.    
  14.     public void ejectQuarter() {  
  15.         System.out.println("Please wait, we're already giving you a Gumball");  
  16.     }  
  17.    
  18.     public void turnCrank() {  
  19.         System.out.println("Turning again doesn't get you another gumball!");  
  20.     }  
  21.    
  22.     public void dispense() {  
  23.         System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter");  
  24.         gumballMachine.releaseBall();  
  25.         if (gumballMachine.getCount() == 0) {  
  26.             gumballMachine.setState(gumballMachine.getSoldOutState());  
  27.         } else {  
  28.             gumballMachine.releaseBall();  
  29.             if (gumballMachine.getCount() > 0) {  
  30.                 gumballMachine.setState(gumballMachine.getNoQuarterState());  
  31.             } else {  
  32.                 System.out.println("Oops, out of gumballs!");  
  33.                 gumballMachine.setState(gumballMachine.getSoldOutState());  
  34.             }  
  35.         }  
  36.     }  
  37.    
  38.     public String toString() {  
  39.         return "despensing two gumballs for your quarter, because YOU'RE A WINNER!";  
  40.     }  
  41. }  


监视器
[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. import java.rmi.RemoteException;  
  4.   
  5. /** 
  6.  *  

  7.  * 糖果监视器,以便取得机器的位置、糖果的库存量以及当前机器的状态 
  8.  * 并打印一份可爱的报告 
  9.  * 这是我们的监视器代码,它使用代理和远程糖果机沟通 
  10.  */  
  11. public class GumballMonitor {  
  12.     GumballMachineRemote gumballMachine;  
  13.       
  14.     public GumballMonitor(GumballMachineRemote gumballMachine) {  
  15.         this.gumballMachine = gumballMachine;  
  16.     }  
  17.       
  18.     public void report() {  
  19.         try {  
  20.             System.out.println("Gumball Machine: " + gumballMachine.getLocation());  
  21.             System.out.println("Current inventory: " + gumballMachine.getCount() + " gumballs");  
  22.             System.out.println("Current State: " + gumballMachine.getState());  
  23.         } catch (RemoteException e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.     }  
  27. }  



糖果机
[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. import java.rmi.RemoteException;  
  4. import java.rmi.server.UnicastRemoteObject;  
  5.   
  6. /** 
  7.  * 糖果机成为一个远程服务 
  8.  * 代理模式: 
  9.  */  
  10. public class GumballMachine extends UnicastRemoteObject implements GumballMachineRemote{  
  11.       
  12.     State soldOutState;         //售空状态  
  13.     State noQuarterState;       //没有投入25分钱  
  14.     State hasQuarterState;      //有25分钱了  
  15.     State soldState;            //出售状态  
  16.     State winnerState;          //10%的中奖率  
  17.       
  18.     State state = soldOutState;  
  19.     int count = 0;  
  20.     String location;            //新增,位置字段         
  21.       
  22.       
  23.     public GumballMachine(String location, int numberGumballs) throws RemoteException{  
  24.         soldOutState = new SoldOutState(this);  
  25.         noQuarterState = new NoQuarterState(this);  
  26.         hasQuarterState = new HasQuarterState(this);  
  27.         soldState = new SoldState(this);  
  28.         winnerState = new WinnerState(this);  
  29.         this.count = numberGumballs;  
  30.         if(numberGumballs > 0) {  
  31.             state = noQuarterState;  
  32.         }  
  33.         this.location = location;  
  34.     }  
  35.       
  36.       
  37.     public String getLocation() {  
  38.         return location;  
  39.     }  
  40.   
  41.   
  42.     public void insertQuarter() {  
  43.         state.insertQuarter();  
  44.     }  
  45.       
  46.       
  47.     public void ejectQuarter() {  
  48.         state.ejectQuarter();  
  49.     }  
  50.       
  51.     public void turnCrank() {  
  52.         state.turnCrank();  
  53.         state.dispense();  
  54.     }  
  55.       
  56.     void setState(State state) {  
  57.         this.state  = state;  
  58.     }  
  59.       
  60.     public State getState() {  
  61.         return state;  
  62.     }  
  63.   
  64.   
  65.     void releaseBall() {  
  66.         System.out.println("A gumball comes rolling out the slot...");  
  67.         if(count != 0) {  
  68.             count = count - 1;  
  69.         }  
  70.     }  
  71.   
  72.   
  73.     public State getSoldOutState() {  
  74.         return soldOutState;  
  75.     }  
  76.   
  77.   
  78.     public State getNoQuarterState() {  
  79.         return noQuarterState;  
  80.     }  
  81.   
  82.   
  83.     public State getHasQuarterState() {  
  84.         return hasQuarterState;  
  85.     }  
  86.   
  87.   
  88.     public State getSoldState() {  
  89.         return soldState;  
  90.     }  
  91.       
  92.       
  93.     public State getWinnerState() {  
  94.         return winnerState;  
  95.     }  
  96.   
  97.   
  98.     public int getCount() {  
  99.         return count;  
  100.     }  
  101.   
  102.   
  103.     public String toString() {  
  104.         StringBuffer result = new StringBuffer();  
  105.         result.append("\nMighty Gumball, Inc.");  
  106.         result.append("\nJava-enabled Standing Gumball Model #2004");  
  107.         result.append("\nInventory: " + count + " gumball");  
  108.         if (count != 1) {  
  109.             result.append("s");  
  110.         }  
  111.         result.append("\n");  
  112.         result.append("Machine is " + state + "\n");  
  113.         return result.toString();  
  114.     }  
  115.       
  116. }  

在RMI registry中注册。。。。。


[java]  view plain  copy
  1. package gumballrmi;  
  2.   
  3. import java.rmi.Naming;  
  4.   
  5. public class GumballMachineTestDrive {  
  6.   
  7.     public static void main(String[] args) {  
  8.         GumballMachineRemote gumballMachine = null;  
  9.         int count = 0;  
  10.           
  11.         if(args.length < 2) {  
  12.             System.out.println("GumballMachine<name> <inventory>");  
  13.             System.exit(1);  
  14.         }  
  15.         try {  
  16.             count = Integer.parseInt(args[1]);  
  17.             gumballMachine = new GumballMachine(args[0], count);  
  18.             Naming.rebind("//" + args[0] + "/gumballmachine", gumballMachine);  
  19.         } catch (Exception e) {  
  20.             e.printStackTrace();  
  21.         }  
  22.     }  
  23. }  

以上也就是制作远程服务的步骤
步骤一:制作远程接口
步骤二:制作远程的实现
步骤三:利用rmic产生的stub和skeleton
步骤四:启动RMI registry
步骤五:开始远程服务

在代理模式中还有虚拟代理和保护代理,在这里就只讨论远程代理,是用得比较多的一种,其他的可以参考《Head First 设计模式》。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值