《Head First 设计模式》学习笔记——代理模式
调用代理的方法,会被代理利用网络转发到远程运行,而且结果会通过网络返回给代理。再由代理将结果返回给客户。
虚拟代理常常直到我们真正须要一个对象的时候才创建它。
当对象在创建前和创建中时。由虚拟代理来扮演对象的替身。对象创建后代理就会将请求直接托付给对象。
实际的代理类是在执行时创建的,在Java中我们称这样的技术为动态代理。
利用Java的动态代理。能够实现保护代理。
import java.rmi.Remote;//用来做rmiregistry lookup的naming类在java.rmi包中
import java.rmi.RemoteException; //extends Remote这表示此接口要用来支持远程调用
public interface GumballMachineRemote extends Remote {
//准备支持的方法,每一个都要抛出RemoteException
//由于每次远程方法调用都必须考虑成“有风险的”
public int getCount() throws RemoteException;
public String getLocation() throws RemoteException; //返回值将从server经过网络运回客户。所以必须是原语类型或可序列化类型
public State getState() throws RemoteException;
} //扩展Serializable接口。使得State可序列化
public interface State extends Serializable {
public void insertQuarter();
public void ejectQuarter();
public void turnCrank();
public void dispense();
} public class HasQuarterState implements State {
private static final long serialVersionUID = 768887299984514010L;
Random randomWinner = new Random(System.currentTimeMillis()); //对于State的每一个市县。我们都在GumballMachine实例变量前面加上transientkeyword,这样就能够高考JVM不要序列化这个字段
transient GumballMachine gumballMachine; //其它方法
} //GumballMachine 要继承UnicastRemoteObject成为一个远程服务
//GumballMachine 也须要实现GumballMachineRemote这个远程接口
public class GumballMachine extends UnicastRemoteObject implements
GumballMachineRemote {
/**
*
*/
private static final long serialVersionUID = -2838970117227273571L;
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State winnerState;
State state = soldOutState;
int count = 0;
String location; //构造器须要抛出RemoteException,由于超类是这样做的
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;
} //其它方法
} //在RMI register中注冊
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 {//须要在实例化代码前加上try/catch。由于我们的构造器可能会抛出异常
count = Integer.parseInt(args[1]); gumballMachine = new GumballMachine(args[0], count); //我们也加入上对Naming.rebind的调用。用gumballmachine的名字公布GumballMachine的stub
Naming.rebind("//" + args[0] + "/gumballmachine", gumballMachine);
} catch (Exception e) {
e.printStackTrace();
}
}
} //GumballMonitorclient
public class GumballMonitor {
//依赖此GumballMachineRemote远程接口,而不是详细的类
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();
}
}
} //监视測试程序
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" }; GumballMonitor[] monitor = new GumballMonitor[location.length]; for (int i = 0; i < location.length; i++) {
try {
//为每一个远程机器创建一个代理,客户从Register中寻找代理,也就是stub对象
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();
}
}
}
class ImageProxy implements Icon {
ImageIcon imageIcon;
URL imageURL;
Thread retrievalThread;
boolean retrieving = false;
//我们将图像的url传入构造器中,这是我们希望显示的图像所在的位置
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) {
//假设已经有了icon,就告诉它画出自己
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 {
//此线程中我们实例化icon对象。其构造器会在图像载入完毕后才返回
imageIcon = new ImageIcon(imageURL, "CD Cover");
//当图像准备好后,我们告诉Swing须要重绘
c.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
});
retrievalThread.start();
}
}
}
}
public class ImageProxyTestDrive {
ImageComponent imageComponent;
JFrame frame = new JFrame("CD Cover Viewer");
JMenuBar menuBar;
JMenu menu;
Hashtable<String, String> cds = new Hashtable<String, String>();
public static void main(String[] args) throws Exception {
ImageProxyTestDrive testDrive = new ImageProxyTestDrive();
}
public ImageProxyTestDrive() throws Exception {
//建立框架和菜单
//创建一个图像代理,并指定初始URL
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;
}
}
}
《Head First 设计模式》学习笔记——代理模式的更多相关文章
- Java-马士兵设计模式学习笔记-代理模式-聚合与继承方式比较
一.概述 1.目标:要在Tank的move()方法做时间代理及日志代理(可以设想以后还要增加很多代理处理),且代理间的顺序可活更换 2.思路: (1)聚合:代理类聚合了被代理类,且代理类及被代理类都实 ...
- Java-马士兵设计模式学习笔记-代理模式-动态代理 调用Proxy.newProxyInstance()
一.概述 1.目标:不自己写代理类,利用Proxy.newProxyInstance()动态生成 2.用到的知识点: (1)//编译源码,生成class,注意编译环境要换成jdk才有compiler, ...
- Java-马士兵设计模式学习笔记-代理模式-动态代理 修改成可以任意修改代理逻辑
一.概述 1.目标:动态代理的代理逻辑可以任意修改 2.思路: (1)要把代理逻辑抽离,站在jvm的角度思考,应独立出InvocationHandler接口,并接收被代理的对象及方法作为参数invok ...
- 设计模式学习心得<代理模式 Proxy>
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 概述 意图 为其他对象提供 ...
- Java设计模式学习记录-代理模式
代理模式 代理模式是常见设计模式的一种,代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...
- 设计模式学习之代理模式(Proxy,结构型模式)(11)
参考地址:http://www.cnblogs.com/zhili/p/ProxyPattern.html 一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访 ...
- javascript设计模式学习之六——代理模式
一.代理模式定义 代理模式的关键是:当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问.代理模式需要和本体对外提供相同的接口,对用户来说是透明的.代理模式的种类有 ...
- 学习笔记——代理模式Proxy
代理模式,主要是逻辑和实现解耦.具体逻辑如何,由代理Proxy自己来设计,我们只需要把逻辑Subject交给代理即可. 主要应用场景,包括创建大开销对象时,使用代理来慢慢创建:远程代理,如网络不确定时 ...
- 设计模式之笔记--代理模式(Proxy)
代理模式(Proxy) 定义 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 类图 描述 Subject,定义了ConcreteSubject和Proxy的共用接口,这样就可以 ...
随机推荐
- Java 基础入门随笔(5) JavaSE版——函数重载
1.函数 函数就是定义在类中具有特定功能的一段独立小程序,也称为方法. 定义函数的格式: 修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,...) { ...
- HDU_1864_最大报销额_01背包
最大报销额 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status ...
- HDU_1203_01背包
I NEED A OFFER! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- Nuxt.js使用详解
首先来讲一下服务端渲染 直白的说就是在服务端拿数据进行解析渲染,直接生成html片段返回给前端.具体用法也有很多种比如: 传统的服务端模板引擎渲染整个页面 服务渲染生成htmll代码块, 前端 AJA ...
- js延时加载的方法
js的延迟加载有助与提高页面的加载速度,以下是延迟加载的几种方法: 1.使用setTimeout延迟方法的加载时间 延迟加载js代码,给网页加载留出更多时间 <script type=" ...
- blog笔录1
(1)虚拟主机 (2)部署 部署完成后刷新页面会看到笑脸,在Home分组下控制器Application/Home/Controller/IndexController.class.php下定义显示 ( ...
- java的标识符和关键词
1.1.1 标识符 可以简单的理解为一个名字.在Java中,我们需要标识代码的很多元素,包括类名.方法.字段.变量.包名等.我们选择的名称就称为标识符,并且遵循以下规则: 标识符可以由字母.数字. ...
- TWaver GIS制作穹顶之下的雾霾地图
“我不满意,我不想等待,我也不再推诿,我要站出来做一点什么.我要做的事,就在此时,就在此刻,就在此地,就在此生”.自离职央视后,沉寂许久的知名记者.主持人柴静昨日携个人视频新作 <穹顶之下> ...
- LeetCode_18 4Sum
Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums s ...
- 骑士游历 - dp
题目地址:http://www.51cpc.com/web/problem.php?id=1586 Summarize: 1. 题目坐标系所给 x,y与惯用表示横纵坐标相反 2. 搜索超时,使用动规: ...