声明:迁移自本人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. plsql调用执行存储过程

    参考 https://www.cnblogs.com/enjoyjava/p/9131169.html ------------------------------------------------ ...

  2. 剑指offer - 栈的压入弹出序列 - JavaScript

    题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1 ...

  3. java 学生信息管理

    题目: 一.测试要求:      1.按照测试内容要求完成程序的设计与编程:      2.将最终结果的源文件(.java)文件上传到以班级为单位,保存源程序.      3.建立学号姓名文件夹,如: ...

  4. POJ 3673:Cow Multiplication

    Cow Multiplication Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12210   Accepted: 85 ...

  5. windows driver 延时

    #define Delay_One_MicroSecond (-10) #define Delay_One_MilliSecond (Delay_One_MicroSecond * 1000) voi ...

  6. bzoj 1832: [AHOI2008]聚会

    良心题2333 三个点两两求一遍就行,最小肯定是在某2个点的lca处,(肯定让第三个人去找2个人,不能让2个人一起去找第三个人233) #include<bits/stdc++.h> #d ...

  7. Java9,8,7中接口的内容

    在Java 9+版本中,接口的内容可以有: 1:成员变量其实是常量格式:[public][static][final] 数据类型 常量名称 =数据值:注意: 常量必须进行赋值,而且一旦赋值不能改变 常 ...

  8. React之生命周期函数(16.3以后新版本)

    学习链接: https://www.jianshu.com/p/514fe21b9914 学习链接:https://zhuanlan.zhihu.com/p/38030418 学习链接:https:/ ...

  9. English Words and Expressions

    Words apprentice 学徒 corny 老套的 obnoxious 作呕的 intermezzo 间奏曲 predate 日期上早于 parenthesis 括号 delimiter 分隔 ...

  10. POJ 1840:Eqs 哈希求解五元方程

    Eqs Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 14169   Accepted: 6972 Description ...