一、引言

结构模式:核心作用就是从程序的结构上实现松耦合,从而扩大整体的类结构,用来解决更大的问题。

二、适配器模式(adapter)

生活中假设笔记本是标准的USB接口但是外置键盘是圆形接口,这时候就需要一个适配器,如下图所示。一端连接笔记本,一端连接键盘。

用途:一个如下的适配器价格低于一个新的键盘价格,键盘可以打字,现在需要打字但是买不起键盘但可以买得起适配器,这是适配器就有用途了。还比如新型的带USB的插座

也是同样的道理,也是适配器。

概念:将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原来由于接口不兼容而不能在一起工作的那些类可以在一起工作。

角色:  目标接口:客户所希望的接口。目标可以是具体的也可以是抽象的的类,也可以是接口。(如下图中电脑所需要的USB接口)

需要适配的类:需要适配的类或适配者类。(如下图中的 "键盘" 类)

适配器类:通过包装一个需要适配的对象,把原来的接口转换成目标接口。(如下图中的适配器产品)

使用场景:旧系统的升级和改造

Java.io.InputStreamReader(InputStream)

Java.io.OutputStreamReader(OutputStream)

【适配器】

/**
* 相当于USB接口
*/
package cn.sxt.adapter; public interface Target {
void handleRequst(); } /***
* 适配器本身(一个转接器),既继承被适配类又实现Target接口(相当于USB接口),中间是2边都要熟悉,功能都得具备
* 类适配器的模式 (因为有继承,extends Adaptee)
*/
package cn.sxt.adapter; public class Adapter extends Adaptee implements Target{ //重写接口USB的handleRequst方法
public void handleRequst() {
super.request();//super指的是Adaptee类对象 request也是它的方法
} }

【被适配对象】

/***
* 被适配的类(就是圆形接口(ps/2接口)键盘)
*/
package cn.sxt.adapter; public class Adaptee {
public void request() {
System.out.println("可以完成客户需要打字的功能"); } }
/***
* 使用对象适配器模式,使用了组合的模式,跟被适配对象整合
*/
package cn.sxt.adapter; public class Adapter2 implements Target{
private Adaptee adaptee; public void handleRequst() {
adaptee.request();
} public Adapter2(Adaptee adaptee) {
super();
this.adaptee = adaptee;
} }

【客户端】

/***
* 客户类:相当于笔记本电脑,只有USB接口
*/
package cn.sxt.adapter; public class Client {
public void test01(Target t) {
t.handleRequst();
} public static void main(String[] args) {
Client client=new Client();//一个只有USB接口的笔记本
Adaptee adpatee=new Adaptee();//一个只有ps/2接口的键盘
Target target=new Adapter();//Target 一个USB接口
client.test01(target); Target target2=new Adapter2(adpatee);
client.test01(target2);//结果一样 }
}

【类图】

三、代理模式(Proxy Pattern)

核心作用:通过代理,控制对对象的访问 ,可以详细控制访问某个或某类对象的方法,在调用方法前做前置处理(如面谈、签合同),

调用这个方法后做后置处理(如收尾款),即AOP的微观实现。

【AOP扩展】

AOP:Aspect Oriented Programming 面向切面编程。核心机制就是代理模式

一个代理可以代理多个明星的业务(面谈、签合同、收尾款)。核心的业务如唱歌还是要明星自己完成。如果代理的明星多的话,那么代理占据很重要的位置。

每次演唱会都有相同的流程可以将一些相同的流程交给代理去做(如面谈、签合同、收尾款)

AOP:流程好多一样,可以把一样的流程handler中的invoke方法中去处理。它的开源框架是:AspectJ

【代理模式详解】

应用场景:

安全代理:屏蔽对真实角色的访问

远程代理:通过代理类处理远程方法的调用(RMI)

延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象(如:一个文档查看软件,文档中有可能一个图片很大,在打开文件时不可能将所有图片都显示出来

可以使用代理,在需要查看图片时,用代理去打开大的图片。新浪微博9宫格,先看到时缩略图,需要看某个图片可以放大看)

开发框架中应用:

Struts2 中拦截器的实现;数据库连接池的关闭处理;Hibernate中延时加载的实现;mybatis中拦截器插件的实现;AspectJ的实现;

Spring中AOP的实现(日志拦截、声明式事务处理);web service ;RMI远程方法的调用。

分类:

静态代理 (静态定义代理类):代理类由我们自己定义

动态代理(动态生成代理类): 代理类由程序(Java工具表)生成。包括:JDK自带的动态代理、javaassist字节码操作库实现、CGLIB(Code Generation Library)、

ASM(底层使用命令,可维护性差)

1、静态代理

【接口】

/***
* 定义一个"明星"接口
*/
package cn.sxt.staticProxy; public interface Star {
void confer(); //面谈
void signContract();//签合同
void bookTicket();//订飞机票
void sing();//唱歌
void collectMoney();//收钱 }

【真实角色】

/***
* 真实角色:明星本身
*/
package cn.sxt.staticProxy; public class RealStar implements Star{ @Override
public void confer() {
System.out.println("真实角色(周杰伦本人):面谈");
} @Override
public void signContract() {
System.out.println("真实角色(周杰伦本人):签合同");
} @Override
public void bookTicket() {
System.out.println("真实角色(周杰伦本人):订飞机票");
} @Override
public void sing() {
System.out.println("真实角色(周杰伦本人):唱歌");
} public void collectMoney() {
System.out.println("真实角色(周杰伦本人):收尾款"); }
}

【代理角色】

/**代理角色:经纪人
*
*/
package cn.sxt.staticProxy; public class ProxyStar implements Star {
private Star realStar; public ProxyStar(Star realStar) {
this.realStar=realStar;
} @Override
public void confer() {
System.out.println("代理角色(经纪人):面谈");
} @Override
public void signContract() {
System.out.println("代理角色(经纪人):签合同");
} @Override
public void bookTicket() {
System.out.println("代理角色(经纪人):订飞机票");
} //代理角色什么都能做但是就是不能唱歌,需要调用真实角色去唱歌
public void sing() {
realStar.sing();
} public void collectMoney() {
System.out.println("代理角色(经纪人):收尾款"); } }

【客户】

/***
* 客户类
*/
package cn.sxt.staticProxy; public class Client {
public static void main(String[] args) {
Star realStar=new RealStar();
Star proxyStar=new ProxyStar(realStar);//代理类需要传进去一个真实的角色(代理对象) proxyStar.confer();
proxyStar.signContract();
proxyStar.bookTicket();
proxyStar.sing();//代理角色(经纪人)需要调用真实角色(周杰伦)去完成唱歌的功能。客户可以只跟经纪人打交道
proxyStar.collectMoney();
}
}

【类图】

2、动态代理

(1) JDK自带动态处理

java.lang.reflect.Proxy  作用:生成代理类和对象

Java.lang.reflect.Invocationhandler(处理器接口) 可以通过invoke方法实现对真实角色的代理访问,每次通过Proxy生成代理类对象时都要指定对应的处理器接口。

【接口】

/***
* 定义一个"明星"接口
*/
package cn.sxt.dynamicProxy; public interface Star {
void confer(); //面谈
void signContract();//签合同
void bookTicket();//订飞机票
void sing();//唱歌
void collectMoney();//收钱 }

【真实角色】

/***
* 真实角色:明星本身
*/
package cn.sxt.dynamicProxy; public class RealStar implements Star{ @Override
public void confer() {
System.out.println("真实角色(周杰伦本人):面谈");
} @Override
public void signContract() {
System.out.println("真实角色(周杰伦本人):签合同");
} @Override
public void bookTicket() {
System.out.println("真实角色(周杰伦本人):订飞机票");
} @Override
public void sing() {
System.out.println("真实角色(周杰伦本人):唱歌");
} public void collectMoney() {
System.out.println("真实角色(周杰伦本人):收尾款"); }
}

【处理核心】

/**
*
*/
package cn.sxt.dynamicProxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class StarHandler implements InvocationHandler {
Star realsStar; public StarHandler(Star realsStar) {
this.realsStar = realsStar;
} public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("####");//代理类不管调用什么方法都会到这里集中报道
System.out.println("真正方法(唱歌)执行前:面谈、签合同、预付款、订机票"); if ( method.getName().equals("sing") ) {//如果是唱歌方法激活真实角色的唱歌方法
method.invoke(realsStar, args);//激活传入对象的 args(形参)方法
}
System.out.println("真正方法(唱歌)执行后:付尾款"); return null;
} }

【客户端】

/**客户类
*
*/
package cn.sxt.dynamicProxy; import java.lang.reflect.Proxy; public class Client {
public static void main(String[] args) {
Star realStar=new RealStar();
StarHandler handler=new StarHandler(realStar);
Star proxyStar=(Star)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[] {Star.class}, handler);//返回一个代理对象 proxyStar
proxyStar.confer();
proxyStar.sing();
proxyStar.collectMoney(); }
}

【类图】

[19/04/25-星期四] GOF23_结构型模式(适配器模式、代理模式)的更多相关文章

  1. [19/04/28-星期日] GOF23_结构型模式(享元模式)

    一.享元模式(FlyWeight,轻量级) [共享类与非共享类] /*** *FlyweightFactory享元工厂类: 创建并管理享元对象,享元池一般设计成键值对 */ package cn.sx ...

  2. 结构型设计模式之代理模式(Proxy)

    结构 意图 为其他对象提供一种代理以控制对这个对象的访问. 适用性 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用P r o x y 模式.下面是一 些可以使用P r o x y 模式常见 ...

  3. 结构型模式(七) 代理模式(Proxy)

    一.动机(Motivate) 在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者.或者系统结构带来很多麻烦.如何在不 ...

  4. Java进阶篇设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  5. Java设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  6. 10.JAVA-接口、工厂模式、代理模式、详解

    1.接口定义 接口属于一个特殊的类,这个类里面只能有抽象方法和全局常量  (该概念在JDK1.8之后被打破,在1.8后接口中还可以定义普通方法和静态方法,在后续章节会详讲) 1.1 接口具有以下几个原 ...

  7. axios 两种异步模式,代理模式 和 异步模式

    axios 两种异步模式,代理模式 和 异步模式

  8. [转载]Java中继承、装饰者模式和代理模式的区别

    [转载]Java中继承.装饰者模式和代理模式的区别 这是我在学Java Web时穿插学习Java设计模式的笔记 我就不转载原文了,直接指路好了: 装饰者模式和继承的区别: https://blog.c ...

  9. 初探Java设计模式2:结构型模式(代理模式,适配器模式等)

    行为型模式 行为型模式关注的是各个类之间的相互作用,将职责划分清楚,使得我们的代码更加地清晰. 策略模式 策略模式太常用了,所以把它放到最前面进行介绍.它比较简单,我就不废话,直接用代码说事吧. 下面 ...

随机推荐

  1. [javaSE] GUI(打开文件对话框)

    使用FileDialog可以打开文件对话框,根据模式不同,可以分为打开文件和保存文件对话框 获取FileDialog对象,new出来,参数:所属Frame对象,String的标题,FileDialog ...

  2. ajax success和error接收了哪些状态码

    ajax和 Http Status 之前一直奇怪ajax发送请求后success 和 error 分界的状态码是多少, 主要很多将ajax的教程也没有提到, 例如, 我用ResponseEntity& ...

  3. BigDecimal 精准加减乘除

    解决了double和float精确度的问题 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效 ...

  4. Excel2010条件格式的位置

    以下是excel2010的条件格式设置方法(英文版) 具体使用方法可以参考 http://office.microsoft.com/zh-cn/excel-help/HA102809768.aspx

  5. [SDOI2014]旅行解题报告

    题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我 ...

  6. windows操作系统用命令提示符查看占用端口号的进程

    在开发中有时我们需要确定哪个占用了8080端口,在windows命令行窗口下执行: 命令执行后打印出来的结果如下所示:

  7. WiFiDog 与 AuthServer

    背景 在一些公共场所(比如公交车.地跌.机场等)连接当地的 WiFi 时会弹出一个验证表单,输入验证信息(比如短信验证码)后就能够通过该 WiFi 联网. 本文将介绍通过 OpenWrt WiFiDo ...

  8. How to save rules of the iptables?

    The easy way is to use iptables-persistent. Install iptables-persistent: sudo apt-get install iptabl ...

  9. Python爬虫教程-01-爬虫介绍

    Spider-01-爬虫介绍 Python 爬虫的知识量不是特别大,但是需要不停和网页打交道,每个网页情况都有所差异,所以对应变能力有些要求 爬虫准备工作 参考资料 精通Python爬虫框架Scrap ...

  10. JS 日期与时间戳相互转化

    1.日期格式转时间戳 function getTimestamp(time) { return Date.parse(new Date(time)); } 2.时间戳转日期格式 function tr ...