-
多用组合,少用继承
-
针对接口编程,不针对实现编程
-
为交互对象之间的松耦合设计而努力
-
类应该对扩展开放,对修改关闭
-
依赖抽象,不要以来具体类
-
只和朋友交谈
-
别找我,我会找你
-
类应该只有一个改变的理由
要点
–
———————————————————————————————————————————————————
-
代理模式为另一个对象提供代表,以便控制客户对对象访问,管理访问的方式有许多种。
-
远程代理管理客户和远程对象之间的交互。
-
虚拟代理控制访问实例化开销大的对象。
-
保护代理基于调用者控制对象方法的访问。
-
代理模式有许多变体,例如:缓存代理、同步代理、防火墙代理和写入时复制代理。
-
代理在结构上类似装饰者,但是目的不同。
-
装饰者模式为对象加上行为,而代理是控制访问。
-
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学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!