一 简介
1.1 生活当中的代理案例
- 房屋中介代理
房屋中介从 包租婆手中获取房源 卖给需要租房的人。
- 商品代购(比如卖面膜)
卖面膜的人 从厂家拿面膜 在朋友圈当中宣传 卖给熟人。
1.2 为什么要使用代理
- 对于消费者而言只需要关注自己需要的商品,可以减少成本,不需要去寻找房源或者渠道,
- 对于生产者(包租婆,厂家)只需要关注自己的产品,销售只需要让代理者去处理就好 关注自家
- 对于代理者而言,可以增加类 扩展业务需求 比如收中介费
1.3代理模式在java当中的应用
- 统一了异常处理
- mybatis使用了代理
- spring aop实现了原理
- 日志框架
1.4概述
- 代理模式(Proxy Pattern):是23中设计模式中的一种,属于结构型的模式,指的是一个对象本身不做实际操作,而是通过其他对象来得到自己想要的结果。
- 意义:目标对象只需要关心自己的实现细节,通过代理对象来实现功能的增强,可以扩展目标对象的功能。
- 体现了非常重要的编程思想:不能随意修改源码,如果需要修改源码,通过修改代理的方式来实现功能的扩展。
1.5图示
- 元素组成
- 接口:定义行为和规范
- 被代理类:是目标对象
- 代理类:做功能增强的
- 值得注意的点
- 用户只需要关注接口功能,而不在乎谁提供了功能。
- 接口真正实现这是目标对象,但是他不与用户接触,而是通过代理。
- 代理就是Proxy,由于它实现了接口,所以他能够与用户直接接触
- 用户调用Proxy的时候,Proxy内部调用了目标对象realSubject。所以Proxy是代理者,它可以增强RealSubject的功能操作。
二 静态代理
2.1 案例
通过代理模式实现日志操作
2.2 实现案例
假设有一个大商场,商场有很多的柜台,有一个柜台卖茅台酒并且增加品尝和是否购买的需求。我们进行代码的模拟。
2.2.1 创建接口SellWine
首先得有一个接口,通用的接口是代理模式实现的基础。这个接口我们命名为 SellWine,代表卖酒这个行为。
public interface SellWine {
void maiJiu();
}
2.2.2 创建目标对象MaiTaiJiu类
这个表示真正的对象,它实现了SellWine接口,卖酒的行为有了
(如果按照原始的方式就是在MaoTaiJiu这个对象的每一个方法当中分别添加pinchang()、isGouMai(),就很麻烦 代码冗余,并且如果想要添加增强类的话就需要这个真实对象的源码)
public class MaoTaiJiu implements SellWine{
public void maiJiu() {
System.out.println("我卖的是茅台酒!");
}
public void baoZhuang(){
System.out.println("茅台酒的包装");
}
public void jiancha(){
System.out.println("茅台酒日期的检查");
}
}
2.2.3 创建Proxy GuiTai类
GuiTai就是一个Proxy对象 他有一个maiJiu()方法,不过在调用maiJiu()方法的时候有一些额外的行为比如说pinchang()、isGouMai()
public class GuiTai implements SellWine {
//代理的是MaoTaiJiu这个真实对象 类型固定了 无法代理别的品牌的酒
private MaoTaiJiu maoTaiJiu;
public void setMaoTaiJiu(MaoTaiJiu maoTaiJiu){
this.maoTaiJiu=maoTaiJiu;
}
/* public GuiTai(MaoTaiJiu maoTaiJiu){
this.maoTaiJiu=maoTaiJiu;
}*/
public void maiJiu() {
pinchang();
maoTaiJiu.maiJiu();
goumai(true);
}
public void pinchang(){
System.out.println("客户您可以品尝!");
}
public void goumai(boolean isMai){
if(isMai){
System.out.println("购买结账!");
}else{
System.out.println("在考虑考虑!");
}
}
}
2.2.4 创建客户 Client类
public class Client {
public static void main(String[] args) {
//真实对象: 茅台酒
MaoTaiJiu maoTaiJiu = new MaoTaiJiu();
//代理对象:柜台
GuiTai guiTai = new GuiTai();
//通过代理角色 来实现真实对象茅台酒的卖酒
//1 获取代理的是茅台酒的
guiTai.setMaoTaiJiu(maoTaiJiu);
guiTai.maiJiu();
}
}
结果:
现在可以看到,代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
上面介绍的是静态代理的内容,为什么叫做静态呢?因为它的类型是事先预定好的
三 动态代理
上一节代码中 GuiTai类是代理,我们需要手动编写代码让 GuiTai 实现 SellWine 接口,而在动态代理中,我们可以让程序在运行的时候自动在内存中创建一个实现 SellWine 接口的代理,而不需要去定义 GuiTai 这个类。这就是它被称为动态的原因。