设计模式

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

远程代理:能够作为还有一个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. Acunetix Web Vulnerability Scanner使用和生成报告的方法

    Acunetix WVS,该扫描软件的全称Acunetix Web Vulnerability Scanner,是一个网站及服务器漏洞扫描软件.它可以检查Web应用程序中的漏洞,如SQL注入.跨站脚本 ...

  2. vc++中 .H 头文件引用的顺序与符号关系

    在使用 #include "math.h"  和 #include <math.h>时,引号 与尖括号的区别如下 此时math.h_1 在工程文件中 math.h_2 ...

  3. sql常用手法(二)

    drop,TRUNCATE和delete的区别 1.DROP删表,表结构将删了,当然数据也不存在了2.TRUNCATE和DELETE删数据,表结构还在3.DELETE可以带条件删除,TRUNCATE是 ...

  4. Scrapy 组件的具体用法

    一.Spider 用法 在 Scrapy 中,要抓取网站的链接配置.抓取逻辑.解析逻辑都是在 Spider 里完成的.Spider 的一些基础属性和基础方法: name:爬虫名字,Spider的名字定 ...

  5. ie7下设置z-index无效如何解决?

    ie7下z-index无效的问题之前做练习的时候遇到过,百度解决掉之后就丢脑后了.今天项目中又发现这个bug,无奈又去百度,这次还是记下来,节省了百度的时间还能小装一把... 需求是这样的: 页面中的 ...

  6. 「 HDU P3555 」 Bomb

    # 题目大意 给出 $\text{T}$ 个数,求 $[1,n]$ 中含 ‘49’ 的数的个数. # 解题思路 求出不含 '49' 的数的个数,用总数减去就是答案. 数位 $DP$,用记忆化来做. 设 ...

  7. 「 COGS 2240 」 X 「 Luogu P2885 」 架设电话线

    解题思路 首先很容易就想到了一个二维的朴素的 $dp$. 设 $dp[i][j]$ 表示第 $i$ 个位置的电话线杆的高度为 $j$ 时的最小花费,就需要枚举第 $i$ 个电话线杆.第 $i$ 个电话 ...

  8. zend studio 12.5.1 window 安装并设置笔记

    下载百度云上的安装包-----------------------------------------------安装时,解决window 10的权限问题 安装完成后的设置设置字体window=> ...

  9. 三 , lnmp 一键包安装使用

    安装打包环境  #https://lnmp.org/----------------------------------------------------#安装wget -c http://soft ...

  10. 【01】CSS制作的图形

    [01]CSS制作的图形   绘制五角星:   通过border绘制三角形.然后通过transfrom来旋转35度. 绘制对称的图形,最后绘制顶部的三角形即可.   元素本身,加上:before和:a ...