设计模式

代理模式:为还有一个对象提供一个替身或占位符以控制对这个对象的訪问。
使用代理模式创建代表对象,让代表对象控制某对象的訪问,被代理的对象能够使远程的对象(远程代理)、创建开销大的对象(虚拟代理),或须要安全控制的对象(保护代理)。

远程代理:能够作为还有一个JVM上对象的本地代表。

调用代理的方法,会被代理利用网络转发到远程运行,而且结果会通过网络返回给代理。再由代理将结果返回给客户。

虚拟代理:作为创建开销大的对象的代表。

虚拟代理常常直到我们真正须要一个对象的时候才创建它。

当对象在创建前和创建中时。由虚拟代理来扮演对象的替身。对象创建后代理就会将请求直接托付给对象。

动态代理:java在java.lang.reflect包中有自己的代理支持,利用这个包你能够在执行时动态的创建一个代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。

实际的代理类是在执行时创建的,在Java中我们称这样的技术为动态代理。

利用Java的动态代理。能够实现保护代理。

防火墙代理:控制网络资源的訪问,保护主题免于“坏客户”的侵害。
智能引用代理:当主题被引用时,进行额外的动作,比如计算一个对象被引用的次数。
缓存代理:为开销大的运算结果提供临时存储,它也执行多个客户共享结果。以降低计算或网络延迟。
同步代理:多线程的情况下为主题提供安全的訪问。
复杂隐藏代理:用来隐藏一个类的复杂集合的复杂度。并进行訪问控制。有时候也成为外观代理。复杂隐藏代理和外观模式不一样,由于代理控制訪问,而外观模式仅仅是提供还有一组接口。
写入时复制代理:用来控制对象的复制,方法是延迟对象的复制,知道客户真正须要为止,这是虚拟代理的变体。

制作远程服务
(1)制作远程接口
(2)制作远程实现
(3)利用rmic产生stub和skeleton
(4)启动RMI registry
(5)開始远程服务

设计原则
封装变化
多用组合。少用继承
针对接口编程,不针对实现编程
为交互对象之间的送耦合设计而努力
类应该对扩展开发,对改动关闭
依赖抽象,而不依赖详细类
仅仅和朋友交谈
别找我。我会找你
类应该仅仅有一个改变的理由

要点
代理在结构上类似装饰者。可是目的不一样。装饰者模式为对象加上行为。而代理则是控制行为。
和其它包装者一样,代理会造成你的设计中类的数目添加。

远程代理
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 设计模式》学习笔记——代理模式的更多相关文章

  1. Java-马士兵设计模式学习笔记-代理模式-聚合与继承方式比较

    一.概述 1.目标:要在Tank的move()方法做时间代理及日志代理(可以设想以后还要增加很多代理处理),且代理间的顺序可活更换 2.思路: (1)聚合:代理类聚合了被代理类,且代理类及被代理类都实 ...

  2. Java-马士兵设计模式学习笔记-代理模式-动态代理 调用Proxy.newProxyInstance()

    一.概述 1.目标:不自己写代理类,利用Proxy.newProxyInstance()动态生成 2.用到的知识点: (1)//编译源码,生成class,注意编译环境要换成jdk才有compiler, ...

  3. Java-马士兵设计模式学习笔记-代理模式-动态代理 修改成可以任意修改代理逻辑

    一.概述 1.目标:动态代理的代理逻辑可以任意修改 2.思路: (1)要把代理逻辑抽离,站在jvm的角度思考,应独立出InvocationHandler接口,并接收被代理的对象及方法作为参数invok ...

  4. 设计模式学习心得<代理模式 Proxy>

    在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 概述 意图 为其他对象提供 ...

  5. Java设计模式学习记录-代理模式

    代理模式 代理模式是常见设计模式的一种,代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...

  6. 设计模式学习之代理模式(Proxy,结构型模式)(11)

    参考地址:http://www.cnblogs.com/zhili/p/ProxyPattern.html 一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访 ...

  7. javascript设计模式学习之六——代理模式

    一.代理模式定义 代理模式的关键是:当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问.代理模式需要和本体对外提供相同的接口,对用户来说是透明的.代理模式的种类有 ...

  8. 学习笔记——代理模式Proxy

    代理模式,主要是逻辑和实现解耦.具体逻辑如何,由代理Proxy自己来设计,我们只需要把逻辑Subject交给代理即可. 主要应用场景,包括创建大开销对象时,使用代理来慢慢创建:远程代理,如网络不确定时 ...

  9. 设计模式之笔记--代理模式(Proxy)

    代理模式(Proxy) 定义 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 类图 描述 Subject,定义了ConcreteSubject和Proxy的共用接口,这样就可以 ...

随机推荐

  1. Dreamweaver启动出错--Designer.xml错误

    Designer.xml错误导致Dreamweaver CS4无法启动 xml parsing fatal error:Invalid document structure,line:1, file: ...

  2. 牛客练习赛25 C 再编号

    解题思路 我们先来观察一下题目中给出的公式 $$a'_i=(\sum_{j=1}^na_j)-a_i$$ 通过这个公式推一下经过再编号后的序列的总和,因为我们推出这个和之后可以进行下一次计算. $$\ ...

  3. Linux基本文件类型

    Linux基本文件类型 基本文件类型 - : 普通文件 d : 文件目录 p : 管道文件 l : 软连接文件 c : 字符设备文件 s : socket文件

  4. LINUX应用开发工程师职位(含答案)

    就业模拟测试题-LINUX应用开发工程师职位 本试卷从考试酷examcoo网站导出,文件格式为mht,请用WORD/WPS打开,并另存为doc/docx格式后再使用 试卷编号:143989试卷录入者: ...

  5. 1. Jenkins 入门使用

    1. 下载jenkins https://pkg.jenkins.io/redhat-stable/ sudo wget -O /etc/yum.repos.d/jenkins.repo https: ...

  6. 戏说云计算之PaaS,IaaS,SaaS

    最近我们聊到"CRM系统PAAS化",有些可能就不了解,到底什么是PAAS.云计算还有IaaS,SaaS概念,这三者之间有什么区别?今天智云通CRM系统小编用通俗易懂的例子跟大家分 ...

  7. session 分布式处理-----https://segmentfault.com/a/1190000013447750?utm_source=tag-newest

    第一种:粘性session 粘性Session是指将用户锁定到某一个服务器上,比如上面说的例子,用户第一次请求时,负载均衡器将用户的请求转发到了A服务器上,如果负载均衡器设置了粘性Session的话, ...

  8. Swift 对象创建(PUT Object)过程详解——基于副本策略(一)

    swift中创建对象,即PUT object,根据选定的存储策略将对象内容写入至相应的服务器(object server).我们重点关注object controller和object servers ...

  9. WEB开发----springboot的登录拦截机制

    如果是一个后台的管理项目的,有些东西是不能直接就可以访问的,必须要登录才可以进去,所以就需要进行登录拦截,只有登录过的用户才可以正常访问. 登录拦截是不会拦截jsp页面的方法,所以我们需要在Contr ...

  10. BZOJ3991 寻宝游戏 LCA 虚树 SET

    5.26 T1:寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄, ...