声明:迁移自本人CSDN博客https://blog.csdn.net/u013365635

在常见的23种设计模式中,static proxy和decorator在代码结构上是特别相似的。那它们的不同具体体现在什么地方呢,本文就通过静态代理模式代码和装饰器模式代码的比较说明这个问题。

本文给出的例子将会尽可能简单的例子,把最核心的接口及继承关系展现出来,以期读者不被繁复的业务逻辑所束缚。

static proxy模式代码如下
接口类

package com.test.designpattern.staticproxyexample;
public interface Subject {
void printString(String url);
}

接口实现类

package com.test.designpattern.staticproxyexample;

public class ConcreteSubject implements Subject {

@Override
public void printString(String url) {
String dataFormUrl = mockNetRequest(url);
System.out.println("data from internet is :" + dataFormUrl);
} private String mockNetRequest(String url) {
return new StringBuilder("data from ").append(url).append(" is:").append("200").toString();
} }

代理类,实现接口类

package com.test.designpattern.staticproxyexample;

public class Proxy implements Subject {
private Subject subject; public Proxy(Subject subject) {
this.subject = subject;
} @Override
public void printString(String url) {
System.out.println("This is a proxy server in hongkong, you can accesss google through it");
subject.printString(url);
} }

测试类

package com.test.designpattern.staticproxyexample;

public class TestStaticProxy {
public static void main(String[] args) {
//如果这里直接访问ConcreteSubject,将因为各种原因受限而返回404,模拟代码实现作为读者的家庭作业
Subject proxySubject = new Proxy(new ConcreteSubject());
proxySubject.printString("https://xxx.xxx.xxx");
}
}

运行结果如下

This is a proxy server in hongkong, you can accesss google through it
data from internet is :data from https://xxx.xxx.xxx is:200

decorator模式代码如下
接口类
package com.test.designpattern.docoratorexample;

public interface Component  {
void printString(String s);
}

接口实现类

package com.test.designpattern.docoratorexample;

public class ConcreteComponent implements Component {
@Override
public void printString(String s) {
System.out.println("Input String is:" + s);
}
}

抽象装饰类,提供了接口方法的一般实现,也可以不需要这个类

package com.test.designpattern.docoratorexample;

public class Decorator implements Component {
private Component component;
public Decorator(Component c) {
component = c;
} @Override
public void printString(String s) {
component.printString(s);
}
}

具体装饰类,完善功能

package com.test.designpattern.docoratorexample;

public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component c) {
super(c);
} @Override
public void printString(String s) {
printPromptMesage();
//保留原有的功能
super.printString(s);
//加强已有的功能
printStringLen(s);
} private void printPromptMesage() {
System.out.println("begin to output message by decorator A");
} private void printStringLen(String s) {
System.out.println("The length of string is:" + s.length());
} }

测试类

package com.test.designpattern.docoratorexample;

public class TestDecorator {
public static void main(String[] args) {
Component myComponent = new ConcreteComponent();
myComponent.printString("A test String");
Decorator myDecorator = new ConcreteDecoratorA(myComponent);
myDecorator.printString("A test String");
}
}

运行结果

Input String is:A test String
begin to output message by decorator A
Input String is:A test String
The length of string is:13

单从代码结构上来讲,静态代理模式和装饰器模式是一样的,但是它们有本质的不同,本文作者挑选的2个例子,尽可能把函数名都写成一样的,但是它们的内涵是不一样的。
从意图上来说,Proxy中模拟在本地直接调用接口实现类ConcreteSubject 无法实现而必须经过Proxy才能实现的功能。Decorator中模拟了完善接口实现类ConcreteComponent的功能。
作者在公司工作的时候,有一个功能是实现限流,就是控制存取磁盘数据的数据流量,这时采用的就是装饰器类而非代理类,装饰器装饰的是Java原生的InputStream、OutputStream。

学习设计模式,最应该认真反复学习的书籍当然是“四人帮”编写的《Design Pattern—Elements of Reusable Object-Oriented Software》.

借用其中的一段话表述Proxy和Decorator的区别。
这2种模式都描述了怎样为对象提供一定程度上的间接引用,proxy和decorator对象的实现部分都保留了指向另一个对象的指针,它们向这个对象发送请求。然而,它们具有不同的设计目的。
像Decorator模式一样,Proxy模式构成一个对象并为用户提供一致的接口,但与Decorator模式不同的是,Proxy模式不能动态地添加或分离性质,它也不是为递归组合而设计的。它的目的是,当直接访问一个实体不方便或者不符合需要时,为这个实体提供一个替代者,例如,实体在远程设备上,访问受到限制或者实体是持久存储的。
在Proxy模式中,实体定义了关键功能,而Proxy提供(或拒绝)对它的访问。

Proxy模式访问模型如下:
Client——>Proxy——>ConcreteSubject,目标在ConcreteSubject,如果Client能直接访问到ConcreteSubject,是不会去麻烦Proxy的。

Decorator模式访问模型如下:
Client——>ConcreteDecorator——>ConcreteComponent,此时的目标不是ConcreteComponent了,就是ConcreteDecorator,因为ConcreteDecorator才能提供Client需要的完整功能。比如上文说的IO限流器。

设计模式讲解2:static proxy和decorator的不同点的更多相关文章

  1. Java设计模式(7)装饰模式(Decorator模式)

    Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...

  2. 设计模式:代理(Proxy)模式

    设计模式:代理(Proxy)模式 一.前言    代理模式或许我们都听说过,至少知道代理(Proxy)这个东西的,否则看这篇博客也没任何意义的.什么叫做代理,代理是代替服务器去接受请求者的请求的中间人 ...

  3. 设计模式讲解4:Bridge模式源码

    声明:迁移自本人CSDN博客https://blog.csdn.net/u013365635 桥接模式可以和排列组合关联起来理解,一个对象有多种不通种类的属性,如attributeA1,attribu ...

  4. 设计模式-代理模式(Proxy Model)

    文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/5988145.html 目录 1.写在前面 2.概述 3.目的 4.结构组成 5.实现 5 ...

  5. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)

    原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...

  6. PHP设计模式之装饰器模式(Decorator)

    PHP设计模式之装饰器模式(Decorator) 装饰器模式 装饰器模式允许我们给一个类添加新的功能,而不改变其原有的结构.这种类型的类属于结构类,它是作为现有的类的一个包装 装饰器模式的应用场景 当 ...

  7. 深入浅出设计模式——代理模式(Proxy Pattern)

    模式动机在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用.代理对象可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象去掉客户不能看到 ...

  8. C#设计模式(9)——装饰者模式(Decorator Pattern)

    一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...

  9. 设计模式之美:Proxy(代理)

    索引 别名 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):使用相同 Subject 接口实现 Proxy. 别名 Surrogate 意图 为其他对象提供一种代理以控制对这个对象的 ...

随机推荐

  1. [洛谷Luogu]P1803 线段覆盖问题

    贪心想法题解的各位dalaodalaodalao都讲得很清楚了,在下就提供一种桶排的做法吧. 因为给出数据范围 0≤ai<bi≤10000000≤ai<bi≤10000000≤ai< ...

  2. [题解] CF932E Team Work

    CF932E Team Work 你现在手里有\(n\)个人,你要选出若干个人来搞事情(不能不选),其中选择\(x\)个人出来的代价是\(x^k\),问所有方案的代价总和. 数据范围:\(1\le n ...

  3. html 如何使表格一列都变颜色的简单方法!!

    html怎么让一列变颜色用到属性colgroup 重点我都加粗了!! <colgroup span="3"  bgcolor="yellow">&l ...

  4. Docker 网络详解及 pipework 源码解读与实践

    转载自:https://www.infoq.cn/article/docker-network-and-pipework-open-source-explanation-practice/ Docke ...

  5. BurpSuite详解

    转载自:http://www.nxadmin.com/tools/689.html 本文由阿德马翻译自国外网站,请尊重劳动成果,转载注明出处 Burp Suite是Web应用程序测试的最佳工具之一,其 ...

  6. 51nod 1429:巧克力

    1429 巧克力 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 现在有两个块巧克力一块大小是   的,另外一块大 ...

  7. 读书笔记 - js高级程序设计 - 第十五章 使用Canvas绘图

    读书笔记 - js高级程序设计 - 第十三章 事件   canvas 具备绘图能力的2D上下文 及文本API 很多浏览器对WebGL的3D上下文支持还不够好   有时候即使浏览器支持,操作系统如果缺缺 ...

  8. git 常见错误

    1.pack exceeds maximum allowed size 解决办法:git config http.postBuffer 52428800

  9. 解决vue-cli3不停请求 /sockjs-node/info?t= 问题

    使用cli3会遇到一直报错get不到/sockjs-node/info?t= 的问题: 如果你的项目没有用到 sockjs,那么就找到报错的地方,将其注释掉即可. 路径在/node_modules/s ...

  10. Spring AOP复习

    最近在翻<Spring In Action>Spring 实战这本书,重新了解了一下AOP的概念和思想并写了一个小Demo示例,记录在这里: 环境:intelliJ IDEA 2018.M ...