声明:迁移自本人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. idea中使用maven运行wordcount代码

    1.创建maven项目 pom文件: <?xml version="1.0" encoding="UTF-8"?> <project xmln ...

  2. Swift Json解析基础

    func JSONToData(obj:Any) -> Data { //先判断是否可以转换 if !JSONSerialization.isValidJSONObject(obj) { ret ...

  3. MSP430系列单片机笔记00

    嵌入式系统 嵌入式系统(Embedded system),是一种“完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”,根据英国电气工程师协会( U.K. Institution of Elect ...

  4. 干货分享:想要写好Proposal,这四个问题必须解决

    当大家确定了毕业论文选题之后,下一步就是着手写开题报告,也就是proposal.开题报告或者说是研究计划要回答四个问题:为什么这个问题重要,为什么这个问题很难解决,为什么现在要考虑解决这个问题,为什么 ...

  5. webpack随笔2--编译ES6/ES7

    一.Babel 1.安装babel Bable-loader: babeljs.io babel最新版:npm install babel-loader@8.0.0-beta.0 @babel/cor ...

  6. EUI库 - 皮肤

      皮肤分离机制    皮肤分离机制对制作可复用的外观比较有优势 那对于只使用一次的皮肤呢?如果也拆分出两个文件,显然不太方便.这里我们针对单次使用的皮肤定制了内部类的功能   每个组件都有一个chi ...

  7. 解决 .NET CORE3.0 MVC视图层不即时编译

    微软官方文档 Razor 编译 Razor SDK 默认启用 Razor 文件的生成时和发布时编译. 启用后,运行时编译将补充生成时编译,允许更新 Razor 文件(如果对其进行编辑). 运行时编译 ...

  8. 送票啦~ | 京东云邀您参加AI顶级盛会GTC CHINA 2019

    本年度不可错过的AI顶级盛会 GTC CHINA2019 即将于12月16–19日在苏州举行 京东云重量级技术专家将携 AI前沿热议话题亮相 京东云相关AI最新动态,也会一并为您带上 小小剧透,快来看 ...

  9. localStorage中使用json

    function setLocalJson(name, json) { json = JSON.stringify(json); localStorage.setItem(name, json)} f ...

  10. Python 使用print实现进度

    import time print("0%",end='') time.sleep(2) print("\r1%",end='') time.sleep(2) ...