设计模式学习--代理模式(Proxy Pattern)

  • 多用组合,少用继承

  • 针对接口编程,不针对实现编程

  • 为交互对象之间的松耦合设计而努力

  • 类应该对扩展开放,对修改关闭

  • 依赖抽象,不要以来具体类

  • 只和朋友交谈

  • 别找我,我会找你

  • 类应该只有一个改变的理由

要点

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

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

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

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

  • 保护代理基于调用者控制对象方法的访问。

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

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

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

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

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

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


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

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

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

远程代理的角色

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

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

在本例子当中,糖果机充当的角色是真正的远程对象,是代理服务的对象。而代理呢,是要通过监视器从远程服务器中注册返回得到的。这里涉及到Java的RMI(远程方法调用),不是设计模式的内容,不多说。

我们要知道的就是,代理对象是通过RMI Registry得到的,它叫做stub(桩),stub扮演的是客户辅助对象,实在客户堆里的;然而在Java RMI中在服务器堆中skeleton(骨架)作为服务辅助对象。

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

来看看糖果机的远程代理实现吧

客户端里有:

GumballMonitor:这是我们的监视器代码,它使用代理来和远程糖果机沟通。

GumballStub:这是我们的代理

服务器端有:

GumballSkeleton:这是我们的服务器辅助对象

GumballMachine:这是我们的服务对象,它为客户暴露一个远程接口以供使用。

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

GumabllMachineRemote接口

package gumballrmi;

import java.rmi.Remote;

import java.rmi.RemoteException;

/**

  • 让GumballMachine准备好当一个远程服务

  • @author wwj

  • 代理模式的使用例子

*/

public interface GumballMachineRemote extends Remote {

public int getCount() throws RemoteException;

public String getLocation() throws RemoteException;

public State getState() throws RemoteException;

}

修改状态接口

package gumballrmi;

import java.io.*;

/**

  • 2013/7/13

  • @author wwj

  • 扩展Serializable接口,则State的所有子类就可以在网络上传送了

*/

public interface State extends Serializable {

public void insertQuarter();

public void ejectQuarter();

public void turnCrank();

public void dispense();

}

修改状态实现类

package gumballrmi;

public class NoQuarterState implements State {

//对于State的每个实现,我们都在GumballMachine实例变量前面加上transient关键字,这就就告诉JVM不要序列化这个字段

transient GumballMachine gumballMachine;

public NoQuarterState(GumballMachine gumballMachine) {

this.gumballMachine = gumballMachine;

}

public void insertQuarter() {

System.out.println(“You inserted a quarter”);

gumballMachine.setState(gumballMachine.getHasQuarterState());

}

public void ejectQuarter() {

System.out.println(“You haven’t inserted a quarter”);

}

public void turnCrank() {

System.out.println(“You turned, but there’s no quarter”);

}

public void dispense() {

System.out.println(“You need to pay first”);

}

public String toString() {

return “waiting for quarter”;

}

}

HasQuarterState.java

package gumballrmi;

import java.util.Random;

public class HasQuarterState implements State {

Random randomWinner = new Random(System.currentTimeMillis()); //随机数产生器

transient GumballMachine gumballMachine;

public HasQuarterState(GumballMachine gumballMachine) {

this.gumballMachine = gumballMachine;

}

public void insertQuarter() {

System.out.println(“You can’t insert another quarter”);

}

public void ejectQuarter() {

System.out.println(“Quarter returned”);

gumballMachine.setState(gumballMachine.getNoQuarterState());

}

public void turnCrank() {

System.out.println(“You turned…”);

int winner = randomWinner.nextInt(10); //参数0~10的随机数

if((winner == 0) && (gumballMachine.getCount() > 1)) { //如果随机树为0,且足够的糖果的话,则可以得到两颗糖果

gumballMachine.setState(gumballMachine.getWinnerState());

} else {

gumballMachine.setState(gumballMachine.getSoldState());

}

}

public void dispense() {

System.out.println(“No gumball dispensed”);

}

public String toString() {

return “waiting for turn of crank”;

}

}

SoldOutState.java

package gumballrmi;

public class SoldOutState implements State {

transient GumballMachine gumballMachine;

public SoldOutState(GumballMachine gumballMachine) {

this.gumballMachine = gumballMachine;

}

public void insertQuarter() {

System.out.println(“You can’t insert a quarter, the machine is sold out”);

}

public void ejectQuarter() {

System.out.println(“You can’t eject, you haven’t inserted a quarter yet”);

}

public void turnCrank() {

System.out.println(“You turned, but there are no gumballs”);

}

public void dispense() {

System.out.println(“No gumball dispensed”);

}

public String toString() {

return “sold out”;

}

}

SoldState.java

package gumballrmi;

public class SoldState implements State {

transient GumballMachine gumballMachine;

public SoldState(GumballMachine gumballMachine) {

this.gumballMachine = gumballMachine;

}

public void insertQuarter() {

System.out.println(“Please wait, we’re already giving you a gumball”);

}

public void ejectQuarter() {

System.out.println(“Sorry, you already turned the crank”);

}

public void turnCrank() {

System.out.println(“Turning twice doesn’t get you another gumball!”);

}

public void dispense() {

gumballMachine.releaseBall();

if (gumballMachine.getCount() > 0) {

gumballMachine.setState(gumballMachine.getNoQuarterState());

} else {

System.out.println(“Oops, out of gumballs!”);

gumballMachine.setState(gumballMachine.getSoldOutState());

}

}

public String toString() {

return “dispensing a gumball”;

}

}

WinnerState.java

package gumballrmi;

public class WinnerState implements State {

transient GumballMachine gumballMachine;

public WinnerState(GumballMachine gumballMachine) {

this.gumballMachine = gumballMachine;

}

public void insertQuarter() {

System.out.println(“Please wait, we’re already giving you a Gumball”);

}

public void ejectQuarter() {

System.out.println(“Please wait, we’re already giving you a Gumball”);

}

public void turnCrank() {

System.out.println(“Turning again doesn’t get you another gumball!”);

}

public void dispense() {

System.out.println(“YOU’RE A WINNER! You get two gumballs for your quarter”);

gumballMachine.releaseBall();

if (gumballMachine.getCount() == 0) {

gumballMachine.setState(gumballMachine.getSoldOutState());

} else {

gumballMachine.releaseBall();

if (gumballMachine.getCount() > 0) {

gumballMachine.setState(gumballMachine.getNoQuarterState());

} else {

System.out.println(“Oops, out of gumballs!”);

gumballMachine.setState(gumballMachine.getSoldOutState());

}

}

}

public String toString() {

return “despensing two gumballs for your quarter, because YOU’RE A WINNER!”;

}

}

监视器

package gumballrmi;

import java.rmi.RemoteException;

/**

  • @author wwj

  • 糖果监视器,以便取得机器的位置、糖果的库存量以及当前机器的状态

  • 并打印一份可爱的报告

  • 这是我们的监视器代码,它使用代理和远程糖果机沟通

*/

public class GumballMonitor {

GumballMachineRemote gumballMachine;

public GumballMonitor(GumballMachineRemote gumballMachine) {

this.gumballMachine = gumballMachine;

}

public void report() {

try {

System.out.println("Gumball Machine: " + gumballMachine.getLocation());

System.out.println(“Current inventory: " + gumballMachine.getCount() + " gumballs”);

System.out.println("Current State: " + gumballMachine.getState());

} catch (RemoteException e) {

e.printStackTrace();

}

}

}

糖果机

package gumballrmi;

import java.rmi.RemoteException;

import java.rmi.server.UnicastRemoteObject;

/**

  • 2013/7/13

  • @author wwj

  • 糖果机成为一个远程服务

  • 代理模式:

*/

public class GumballMachine extends UnicastRemoteObject implements GumballMachineRemote{

State soldOutState; //售空状态

State noQuarterState; //没有投入25分钱

最后

一线互联网Android面试题含详解(初级到高级专题)

这些题目是今年群友去腾讯、百度、小米、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。并且大多数都整理了答案,熟悉这些知识点会大大增加通过前两轮技术面试的几率

如果设置门槛,很多开发者朋友会因此错过这套高级架构资料,错过提升成为架构师的可能。这就失去了我们的初衷;让更多人都能通过高效高质量的学习,提升自己的技术和格局,升职加薪。

最后送给大家一句话,望共勉,永远不要放弃自己的梦想和追求;
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

}

}

}

糖果机

package gumballrmi;

import java.rmi.RemoteException;

import java.rmi.server.UnicastRemoteObject;

/**

  • 2013/7/13

  • @author wwj

  • 糖果机成为一个远程服务

  • 代理模式:

*/

public class GumballMachine extends UnicastRemoteObject implements GumballMachineRemote{

State soldOutState; //售空状态

State noQuarterState; //没有投入25分钱

最后

一线互联网Android面试题含详解(初级到高级专题)

这些题目是今年群友去腾讯、百度、小米、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。并且大多数都整理了答案,熟悉这些知识点会大大增加通过前两轮技术面试的几率

[外链图片转存中…(img-8k5KWt7q-1715394400724)]

如果设置门槛,很多开发者朋友会因此错过这套高级架构资料,错过提升成为架构师的可能。这就失去了我们的初衷;让更多人都能通过高效高质量的学习,提升自己的技术和格局,升职加薪。

最后送给大家一句话,望共勉,永远不要放弃自己的梦想和追求;
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值