更好的理解装饰设计模式和代理设计模式


最近在一个小项目中,出现装饰模式和代理模式。有时感觉它们很像。。好好整理了下,发现还是。。。


对装饰者和被装饰者都实现同一个接口,对代理模式来说,代理类和真实处理的类,都实现同一个接口,此外,不论我们使用的是哪一个接口,都可以很容易地在真实的对象的方法前面或者后面加上自定义的方法。然而,实际上装饰器模式关注在一个对旬上动态的添加方法,然而代理模式关注于控制对象的访问。通俗的说,就是代理类可以的它的客户隐藏一个对象的具体信息,因此,我们用代理模式的时候,我们常常 一个代表类中创建一个对象的实例。并且,当我们使用装饰器模式的时候,通常我们做的是将原始对象作为一个参数传给装饰者的构造器。

下面通过这个过滤器看下装饰类是如何用的?

import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;public class EncodingFilter implements Filter {private String encode=null;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {//拿到配置文件中的编码值this.encode=filterConfig.getServletContext().getInitParameter("encode");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {response.setContentType("text/html;charset="+encode);chain.doFilter(new MyHttpServletRequest((HttpServletRequest) request), response);}//装饰类,用来改变不某些不想要的方法,装饰类,装饰request对象,改造和获取请求参数相关的三个方法,改造成获取有乱码的值,解决乱码后返回// 这样一来,包装过后的request,虽然内部还是乱码,但是通过方法获取时,是解决过后没有乱码的值class MyHttpServletRequest extends HttpServletRequestWrapper{private HttpServletRequest request=null;private boolean EncodehasNode=true;//构造方法public MyHttpServletRequest(HttpServletRequest request) {super(request);this.request=request;}//复写三个方法*//*** Returns a java.util.Map of the parameters of this request. Request* parameters are extra information sent with the request. For HTTP* servlets, parameters are contained in the query string or posted form* data.* * @return an immutable java.util.Map containing parameter names as keys and*         parameter values as map values. The keys in the parameter map are*         of type String. The values in the parameter map are of type*         String array.*//*//这三个方法是ServeltRequest接口身上的抽象方法@Overridepublic Map<String, String[]> getParameterMap() {try {if(request.getMethod().equals("POST")){//--POST提交,一行代码解决乱码,返回request.setCharacterEncoding(encode);                              //return getParameterMap();return request.getParameterMap();}else if(request.getMethod().equals("GET")){//--GET提交获取有乱码的Map,手动编解码解决返回Map<String, String[]> map=request.getParameterMap();if(EncodehasNode){for(Entry<String, String[]> entry: map.entrySet() ){String [] vs=entry.getValue();for(int i=0;i<vs.length;i++){//解码//底层解码原理:/***static char[] decode(String charsetName, byte[] ba, int off, int len)throws UnsupportedEncodingException{StringDecoder sd = deref(decoder);String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;if ((sd == null) || !(csn.equals(sd.requestedCharsetName())|| csn.equals(sd.charsetName()))) {sd = null;try {Charset cs = lookupCharset(csn);if (cs != null)sd = new StringDecoder(cs, csn);} catch (IllegalCharsetNameException x) {}if (sd == null)throw new UnsupportedEncodingException(csn);set(decoder, sd);}return sd.decode(ba, off, len);} ****/vs[i]=new String(vs[i].getBytes("iso8859-1"),encode);}}//执行完第一次后,就把它置为false,因为第一次就都编译好了EncodehasNode=false;}return map;}else{//其他格式,就返回return getParameterMap();}} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}@Overridepublic String getParameter(String name) {//调用getParameterValues得到第0位String vs[]=getParameterValues(name);//判断是名字是不是为空return vs ==null ? null:vs[0];}@Overridepublic String[] getParameterValues(String name) {return  getParameterMap().get(name);}}@Overridepublic void destroy() {}}

装饰者模式的特点为:
1、装饰者和被装饰者对象有相同的超类型。
2、你可以用一个或多个装饰者包装一个对象
3、那么我们知道装饰和被装饰者有相同的超类型,所以在任何须要原始对象(被包装)的对象场合,可以用装饰过的对象代替它。
4、装饰者可以在所委托被装饰者的行为之前/或之后,加上自己行为,以达到特定的目的。
5.对象可以在任何时候被装饰

代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。

代理模式的变种相当多。如动态代理,虚拟代理,保护代理,远程代理。。

我们的EJB技术就是用到了代理模式。

接口:

<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>package bean;import javax.ejb.Remote;@Remote
public interface LoginRemote {public boolean login(String id, String pwd);
}</strong></span>

实例类:

<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>import java.util.Iterator;
import javax.annotation.Resource;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.sql.DataSource;
import model.User;@Stateless
@Remote(LoginRemote.class)
public class Login implements LoginRemote {@PersistenceContextprotected EntityManager em;public Login() {}@Resource(mappedName = "java:jboss/myDataSource")DataSource myDb;@Overridepublic boolean login(String id, String pwd) {Query query = em.createQuery("select u from User u");Iterator iter = query.getResultList().iterator();System.out.println(iter.hasNext());while(iter.hasNext()) {User user = (User)iter.next();if(id.equals(user.getId()) && pwd.equals(user.getPwd())) {return true;    }}return false;}}</strong></span>


测试类,实际上也就是客户端,通过调用接口,来达到实现的目的。。

<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>import bean.Login;public class Test {public static void main(String args) {new Login().login("haha", "haha");}
}</strong></span>


客户端通过调用
远程接口或本地接口。。来达到实现接口的方法。。这种被称为远程代理。就如同我们开时开3389远程
端口一样。通过远程桌面进行服务器进行访部操作。远程桌面就是起到了一个代理的作用。

远程代理
远程代理可以为作为另个JVM上对象的本地代表,调用代理的方法,会被代理利用网络转发到远程执行,并且结果会
通过网络返回给代理。。再由代理将结果转给客户。

虚拟代理
虚拟代理作为开销大的对象的代表。虚拟代理经常直到我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时由虚拟代理来扮演对象的替身,对象创建后,代理就会将请求直接委托给对象。。

核心对比:代理很像装饰者,很容易让大家以为是用一个对象把另一个包起来。然后委托一个实现方法。如动态代理是给IncovationHandler接口。通过回调,在invoke方法中进行修改你方法达到你想要的。我在这里主要理解的是。。它们虽然你,但是目的不同,因为装饰者为对象境加行为,而代理是控制对象的访问。你可能想到的是:显示在”加载中“消息,难道不是在增加行为,从一定程度上说,这的确可以算是,但是,更重要的是,代理是控制对某一个你要想改造的方法的访问,可以参考(我的另一篇博文(通个一个工具类更深理解动态代理),如何控制访问呢?代理将用户从改造的方法解耦了,就是一种两全其美的方法,用到这个方法时,通过代理是一种情况,不用到代理时,照样能很好的实现它原来的作用。。
我们给用户使用的是代理,而不是直正的对象。

通常来说。工厂也能做到这一点,只要你提供原料在工厂中实例化,返加主题,就变了。不同的原料
返回的主题也不同。代理同样也能达到这种效果。用户不知道也不在乎他使用的是代理还是真实的对象。

写到这里,突然又想起一个家伙。适配器。。因为不想一下代理和适配器都是挡在其他对象的前面,并负责请求转以给它们适配器会改变对象适配器的接口。而代理是实现相同的接口。打个比方,同样买到香港的电脑,我们知道香港的插孔和大陆的插孔是不一样的。可以通过代理去买。也可以直接在海淘然后发货给你。代理会按照你的要求(接口),买成大陆通用的版本,而香港卖家可能并不知道,你的具体需求,因为全世界这么多买家,他可能只会给你一套通用的插口。可以转换各个国家具体的插孔。这样转换头就是一个适配器。。

更好的理解装饰设计模式和代理设计模式相关推荐

  1. 外观模式和代理模式的联系和区别_设计模式之代理设计模式

    原文首发于微信公众号:jzman-blog,欢迎关注交流! 今天来看一下什么是代理设计模式,顾名思义,代理就是通过中介代替某人做某一件事,对应到我们的程序中就是通过代理对象来控制某个具体对象某个方法的 ...

  2. 装饰设计模式,代理设计模式 最通俗易懂的案例

    import java.lang.reflect.Method;import org.springframework.cglib.proxy.Enhancer; import org.springfr ...

  3. GoF设计模式之代理设计模式

    该文章首发于GoF设计模式-代理模式 概述 代理模式(Proxy Pattern),为其他对象提供一种代理以控制对这个对象的访问. 代理模式其实就是在访问对象时引入一定程度的间接性,因为这种间接性,可 ...

  4. java之 代理设计模式

    1. 设计一个案例来实现租房功能.分析:在租房的过程中涉及到了3个对象,房东,中介,房客. 中介和房客具有相同的功能--租房. 可以设计如下: 2.上图的设计实际上就是一个代理设计模式---静态代理设 ...

  5. 静态代理和动态代理设计模式

    为什么需要静态代理和动态代理? 不知道,说不清楚,说不好.... 静态代理设计模式: ①找到需要增强处理的类实现的接口 //玩家类实现的接口 public interface Player{boole ...

  6. 【Spring AOP】静态代理设计模式、Spring 动态代理开发详解、切入点详解(切入点表达式、切入点函数)

    AOP 编程 静态代理设计模式 1. 为什么需要代理设计模式 2. 代理设计模式 名词解释 代理开发的核心要素 静态代理编码 静态代理存在的问题 Spring 动态代理开发 搭建开发环境 Spring ...

  7. Java抽象类(abstract)的定义和设计模式(模板设计模式)

    1.抽象类 package com.itstudy.bean;//抽象类/*** 抽象类:描述的内容不是具体的内容* 1.有abstract修改,并且有抽象方法* 2.一共类中有抽象方法,那么这个类一 ...

  8. 设计模式|代理模式、以《安家》为模型轻松理解静态代理和动态代理

    目录 代理模式概念 代理模式实例 静态代理 动态代理 代理模式概念 代理模式是设计模式中运用较广泛且容易理解的一个.代理模式的概念是为其他对象提供一个代理,以控制这个对象的访问,代理对象在客户端和目标 ...

  9. Java中的设计模式:“代理模式”的理解

    代理模式定义: 为其他对象提供一种代理以控制对这个对象的访问.在面向对象中,有时候直接访问一些对象比较麻烦,所以代理模式就是在这个对象上加上一个访问该对象的访问层.类似于很多明星的事务实际都是交给经纪 ...

  10. Java 设计模式_代理模式(2016-08-19)

    概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

最新文章

  1. URLCache探索
  2. 前端学习(604):编程语言
  3. vim查找关键字_vim常用命令及操作
  4. 3D建模场景怎么做?今天的干货来啦,机不可失失不再来
  5. 中国如何在 AI 芯片实现弯道超车?
  6. 支持树莓派的路由器系统_真香!国产64位树莓派系统上手评测
  7. 应用随机过程-复习笔记-Chapter4-关于期望的各态历经性习题答案
  8. 几种平均数的物理意义应用场景
  9. word模板动态填充并下载
  10. 5G C-V2X技术介绍
  11. 智能眼镜上可否能有“MIUI”?
  12. resultMap使用不当导致出现There is no WRITEABLE property named 'student_id' in class 'com.ssi.model.Stud
  13. vsjitdebugger.exe 进程解决方法
  14. SpeechSynthesisUtterance文字转语音播报
  15. display:flex的讲解
  16. 推荐算法实践-章节三-推荐系统冷启动问题-阅读总结
  17. Linux虚拟机不显示IP地址的三种解决方法
  18. Artificial Intelligence Computer Vision ML and DL
  19. web端生成pdf,前端生成pdf导出并自定义页眉页脚
  20. Gateway网关简介及使用。Spring Cloud Alibaba---Gateway概述、简单示例。什么是Gataway网关?网关能干什么?Spring Cloud如何搭建一个网关。

热门文章

  1. GIS_WGS84经纬度坐标系_Web墨卡托坐标系_相互转换代码
  2. 论文笔记_S2D.42_2018-CRV_为经典图像处理辩护:在CPU上的快速深度补全
  3. 【linux基础】linux不能进入系统
  4. 结队编程思路及感悟(python、tkinter、mysql、腾讯云短信等)
  5. Win10技巧:如何确定电脑是否适用Hyper-V虚拟机?
  6. python 与 json
  7. hdu 1217 Arbitrage (最小生成树)
  8. 魔方机器人之下位机编程----串口接收数据并解析
  9. 麻雀算法改进的深度极限学习机DELM的分类 - 附代码
  10. 基于麻雀搜索算法优化的SVM回归预测 - 附代码