设计模式

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

远程代理:能够作为还有一个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. Spartan6系列之芯片配置模式详解

    1.   配置概述 Spartan6系列FPGA通过把应用程序数据导入芯片内部存储器完成芯片的配置.Spart-6 FPGA可以自己从外部非易失性存储器导入编程数据,或者通过外界的微处理器.DSP等对 ...

  2. 关于.Net的强名称(Strong Name)

    下面是我在CSDN上发表的<关于.Net的强名称(Strong Name)>,转载于此. 关于.Net的强名称(Strong Name)  

  3. solr 6.5.1 linux 环境安装

    前言 最近在研究搜索引擎,准备搭建一套属于自己的搜索APP,用于搜索的数据我已通过scrapy抓到本地了,现在需要一个搜索引擎来跑这些数据.于是选择了基于Lucene的solr来为我做搜索引擎的工作. ...

  4. 学习SpringBoot中遇见的坑

    1. 在搭建SpringBoot HelloWorld 时项目结构应该这样: 而不能这样: 否则访问时出现错误页面: 原因:此时还不知道,先记录下来. --已解决2018/12/11,因为Spring ...

  5. php第二十七节课

    注册审核 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  6. 03匿名内部类、eclipse快捷键、String相关知识

    03匿名内部类.eclipse快捷键.String相关知识-2018.7.11 1.匿名内部类(只针对重写一个方法时候使用,不能向下转型,因为没有子类类名) new Inter(){ public v ...

  7. 信息的表示和处理 及 CS:APP 15213 datalab

    信息的表示和处理 在通用计算机中中,字节作为最为最小 的可寻址的内存单元,而不是访问内存中单独的位. 寻址和字节顺序 big endian (大端法),数据最高字节部分地址在地址处,和人的感觉逻辑相似 ...

  8. Vue2 + Koa2 实现后台管理系统

    看了些 koa2 与 Vue2 的资料,模仿着做了一个基本的后台管理系统,包括增.删.改.查与图片上传. 工程目录: 由于 koa2 用到了 async await 语法,所以 node 的版本需要至 ...

  9. 782B The Meeting Place Cannot Be Changed(二分)

    链接:http://codeforces.com/problemset/problem/782/B 题意: N个点,需要找到一个点使得每个点到这个点耗时最小,每个点都同时开始,且都拥有自己的速度 题解 ...

  10. java 反射运用

    一,获取私有的属性,方法,构造器(俗名:暴力反射) 现有一个类,属性,方法,构造器均为私有的,如何创建实例对象,更该属性值,调用方法? public class Student { private S ...