Proxy模式

Proxy是代理人的意思,指代替别人进行工作的人。

代理人可以代替本人完成一部分工作,如果代理人自己完不成,再寻找本人完成。

比如你委托租房中介帮你找房子,找房子的事情由他完成,需要签合同则由他来通知你亲自完成。

示例程序

程序描述

下面一段程序实现了:遇到简单任务,由代理类PrinterProxy完成;遇到代理类完不成的任务,PrinterProxy交给Printer完成的功能。

类图

程序

Printable接口

定义了一个打印机所具备的功能(方法)

public interface Printable {
public abstract void setPrinterName(String name); // 设置名字
public abstract String getPrinterName(); // 获取名字
public abstract void print(String string); // 显示文字(打印输出)
}

Printer类

实现了Printable接口的3个功能,增加了一个heavyJob方法,在构造类时调用,表示构造Printer类是一个耗时的过程

public class Printer implements Printable {
private String name;
public Printer() {
heavyJob("正在生成Printer的实例");
}
public Printer(String name) { // 构造函数
this.name = name;
heavyJob("正在生成Printer的实例(" + name + ")");
}
public void setPrinterName(String name) { // 设置名字
this.name = name;
}
public String getPrinterName() { // 获取名字
return name;
}
public void print(String string) { // 显示带打印机名字的文字
System.out.println("=== " + name + " ===");
System.out.println(string);
}
private void heavyJob(String msg) { // 重活
System.out.print(msg);
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.print(".");
}
System.out.println("结束。");
}
}

PrinterProxy类

也实现了Printable接口的功能,同时内部有一个Printer的实例。干“轻活”,比如设置和输出name时,只需要PrinterProxy类出马即可快速完成;直到干“重活”,即调用print方法时,才生成Printer的实例,让这个实例来完成工作。

public class PrinterProxy implements Printable {
private String name; // 名字
private Printer real; // “本人”
public PrinterProxy() {
}
public PrinterProxy(String name) { // 构造函数
this.name = name;
}
public synchronized void setPrinterName(String name) { // 设置名字
if (real != null) {
real.setPrinterName(name); // 同时设置“本人”的名字
}
this.name = name;
}
public String getPrinterName() { // 获取名字
return name;
}
public void print(String string) { // 显示
realize();
real.print(string);
}
private synchronized void realize() { // 生成“本人”
if (real == null) {
real = new Printer(name);
}
}
}

Main和结果输出

public class Main {
public static void main(String[] args) {
Printable p = new PrinterProxy("Alice");
System.out.println("现在的名字是" + p.getPrinterName() + "。");
p.setPrinterName("Bob");
System.out.println("现在的名字是" + p.getPrinterName() + "。");
p.print("Hello, world.");
}
}
现在的名字是Alice。
现在的名字是Bob。
正在生成Printer的实例(Bob).....结束。
=== Bob ===
Hello, world.

角色和类图

角色

  • Subject(主体)

Subject接口定义了使Proxy和RealSubject之间具有的统一接口。Subject角色的存在,使得Client不必在意它所使用的是Proxy角色还是RealSubject角色。本例中,由Printable接口扮演此角色。

  • Proxy(代理人)

Proxy角色实现了Subject接口的API,会尽量处理来自Client的请求,只有当它不能处理时才将工作交给RealSubject角色。Proxy角色里面包含了一个RealSubject引用,只有必要时才会生成RealSubject角色。本例中由PrintProxy类扮演此角色。

  • RealSubject(实际的主体)

RealSubject在Proxy无法胜任时出场,它与Proxy角色一样实现了Subject接口的API。本例中由Printer类扮演此角色。

  • Client(请求者)

使用Proxy模式的角色,本例中由Main类扮演。

模式类图

思路拓展

提升速度

在本例中,把基础工作交给代理人来完成,将耗时的处理(生成实例)推迟至调用print方法时才进行。

举一个实际的例子:打开一个包含大量图片的Word文档,文档不会一次加载所有图片,只有当用户浏览到图片时才加载,这样做能显著提升文档打开速度。

代理与委托

在程序中,代理人遇到自己无法处理的问题,会委托本人去处理。

这里的委托是设计模式中的委托,指一个类调用另一个类的实例去完成一项工作。不要与现实生活中的委托搞混,它们的意思刚好相反。

Http代理

Http代理服务器是介于服务器和客户端之间的,为web页面提供高速缓存功能(实际上不止这一种功能)的软件。

也可以认为其使用了代理模式。

与其他模式的关联

Decorator模式

Decorator模式主要用来增加新功能

Proxy模式更加侧重于通过代理人来减轻本人负担

《图解设计模式》读书笔记9-2 Proxy模式的更多相关文章

  1. HeadFirst设计模式读书笔记(3)-装饰者模式(Decorator Pattern)

    装饰者模式:动态地将责任附件到对象上.若要扩展功能,装饰者提东了比继承更有弹性的替代方案. 装饰者和被装饰对象有相同的超类型 你可以用一个或者多个装饰者包装一个对象. 既然装饰者和被装饰对象有相同的超 ...

  2. HeadFirst设计模式读书笔记--目录

    HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern) HeadFirst设计模式读书笔记(2)-观察者模式(Observer Pattern) HeadFirst设计 ...

  3. Head First 设计模式读书笔记(1)-策略模式

    一.策略模式的定义 策略模式定义了算法族,分别封装起来,让它们之间可以互换替换,此模式让算法的变化独立使用算法的客户. 二.使用策略模式的一个例子 2.1引出问题 某公司做了一套模拟鸭子的游戏:该游戏 ...

  4. JavaScript设计模式:读书笔记(未完)

    该篇随我读书的进度持续更新阅读书目:<JavaScript设计模式> 2016/3/30 2016/3/31 2016/4/8 2016/3/30: 模式是一种可复用的解决方案,可用于解决 ...

  5. 图解http读书笔记

    以前对HTTP协议一知半解,一直不清楚前端需要对于HTTP了解到什么程度,知道接触的东西多了,对于性能优化.服务端的配合和学习中也渐渐了解到了HTTP基础的重要性,看了一些大神对HTTP书籍的推荐,也 ...

  6. Java设计模式学习笔记(二) 简单工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 正文开始... 1. 简介 简单工厂模式不属于GoF23中设计模式之一,但在软件开发中应用也较为 ...

  7. Java设计模式学习笔记(三) 工厂方法模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...

  8. Java设计模式学习笔记(四) 抽象工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 抽象工厂模式概述 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问 ...

  9. C#设计模式学习笔记:(23)解释器模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8242238.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第十一个模式-- ...

  10. 设计模式之(三)Proxy模式

    今天学习Proxy模式.代理模式是在对已有对象操作困难或者不太方便时,选择用代理的方式对对象进行访问.Proxy实现的方法必须和被代理对象一致. 举一个简单的例子, 有一个Math类实现了IMath接 ...

随机推荐

  1. Excel如何通过关键字模糊匹配查找全称

    打开excel,以其素材为例,通过关键字模糊匹配查找全称.   在公司名下输入公式:=LOOKUP(1,0/FIND(D2,A2:A5),A2:A5),按回车键确定即可.   FIND(D2,A2:A ...

  2. nodeJS打包安装和问题处理

    一,执行步骤,打包报错 1,查看npm版本npm -v 2,查看gulp版本(报错怎么证明没安装)gulp --version 3,安装gulpnpm install --global gulp-cl ...

  3. linux基本命令之磁盘管理命令(ls,cd,pwd,mkdir,rmdir,clear, touch)

    linux磁盘管理命令 1.ls(list)命令:列出目录内容. 格式:ls [参数][文件或目录] ls -a或-all表示列出所有文件和目录,以点开始的是影藏文件,例如,.bash_history ...

  4. PowerEdge T630服务器安装机器学习环境(Ubuntu18.04、Nvidia 1080Ti驱动、CUDA及CUDNN安装)

    安装步骤 在开始安装之前,我要说明一下,这个Ubuntu18.04系统的安装,使用的连接线(就是服务器和电脑显示器的连接线)必须两头都是VGA连接线,不能使用VGA转HDMI连接线,也不能用DVI转D ...

  5. Python 实现类似sed命令的字符串替换小程序

    环境 PyCharm, Windows 背景 sed命令 sed 's/原字符串/新字符串' 单引号中间是s表示替换,原字符串就是要被替换掉的字符串,新字符串就是想要的字符串. 效果 在命令行输入py ...

  6. Nginx1.3.15导致Wordpress,Drupal等框架无限重定向的解决方案

    Wordpress建立的站点出现无限循环重定向问题.很多人遇到这个问题,并不是单纯Wordpress,Drupal, PHPCake等框架也都遇到同样的问题. 新版本的Nginx在收到 http:// ...

  7. UVa10426

    GCD Extreme(II) Input: Standard Input Output: Standard Output Given the value of N, you will have to ...

  8. 高并发-原子性-AtomicInteger

    线程不安全: //请求总次数private static int totalCount = 10000;//最大并发数private static int totalCurrency = 100;// ...

  9. Python之常用模块一(主要RE和collections)

    一.认识模块  什么是模块:一个模块就是一个包含了python定义和声明的文件,文件名就是加上.py的后缀,但其实import加载的模块分为四个通用类别 : 1.使用python编写的代码(.py文件 ...

  10. 【LuoguP3264】[JLOI2015] 管道连接(斯坦那树)

    题目链接 题目描述 小铭铭最近进入了某情报部门,该部门正在被如何建立安全的通道连接困扰.该部门有 n 个情报站,用 1 到 n 的整数编号.给出 m 对情报站 ui;vi 和费用 wi,表示情报站 u ...