【设计模式】代理模式(静态代理与动态代理)

代理模式

代理模式是Spring AOP 中大量使用的设计模式,面向切面编程的底层就是使用的代理模式,所以代理模式是比较重要的

一 概述

什么是代理模式
  • 概念:为其他对象提供一种代理以控制对这个对象的访问
  • 什么意思呢,我们举个例子,租房公司都知道吧,我们想要去租房或者出租房子都会委托给租房公司,因为对于租客来说租房公司有着许多资源,而且随时可以去看房,对于房东来说,他可以避免随时需要去带领租客看房并且商量价格,只需要关注租房本身这件事上,其他的事情都可以交给租房公司。这样的模式就是代理模式。
    在这里插入图片描述
模式的角色

关于代理模式,我们有四个角色

  • 抽象角色:一般会使用接口或者抽象类来解决。
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人。

二 静态代理与动态代理

静态代理
  • 下面,我们通过代码实现上面的例子
    1.抽象角色:定义了真实角色与代理角色需要实现的方法
//租房
public interface Rent {
	public void rent();
}

2.真实角色:房东

public class Host implements Rent{

	@Override
	public void rent() {
		System.out.println("房东出租房子");
	}

}

3.代理角色:中介

public class Proxy implements Rent{
	private Host host;
	
	public Proxy(Host host) {
		this.host = host;
	}
	@Override
	public void rent() {
		seeHouse();
		host.rent();
		getMoney();
	}
	public void seeHouse(){
		System.out.println("中介带你看房子");
	}
	public void getMoney(){
		System.out.println("交钱");
	}

}

4。访客(主函数)

public class MainClass {
	public static void main(String[] args) {
		Host host = new Host();
		Proxy p = new Proxy(host);
		p.rent();
	}
}

结果:
在这里插入图片描述
这样我们就实现了代理模式。通过中介来租房子
但是,我们发现,这样的代理类是写死的,由于每当有一个真实的角色,都需要再来一个对应的代理角色,工作量太大,不易管理。并且代理与真实角色都实现的同一个接口,接口一旦发生改变,代理类也得相应修改
所以我们引出了动态代理

动态代理

在这篇文章中我使用的是JDK实现动态代理,还有一种方式是通过CGLIB实现动态代理,JDK实现的的动态代理只适合于有接口的类,对于没有接口的类只能使用其他方法
在看动态代理之前,你需要一些反射的知识,了解反射包中的Proxy与InvocationHandler两个类

  • Proxy 是用来生成动态代理的实例的,就是代理对象。
  • InvocationHandler 是由代理实例的调用处理实现的接口的。
    我们将上面实现的代理类删除,写一个动态生成代理类的处理类
public class ProxyInvocationHandler implements InvocationHandler{
	//被代理的接口
	private Object oj;
	
	public void setRent(Object oj){
		this.oj = oj;
	}
	
	//通过反射得到一个代理对象
	public Object getProxy(){
		return Proxy.newProxyInstance(this.getClass().getClassLoader(),
				oj.getClass().getInterfaces(),
				this);
	}
	
	//处理代理实例,并返回结果
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		//选择要执行的接口上的方法
		seeHouse();
		Object result = method.invoke(oj, args);
		getMoney();
		return result;
	}
	
	public void seeHouse(){
		System.out.println("中介带你看房子");
	}
	
	public void getMoney(){
		System.out.println("交钱");
	}
}

再看主函数

public class MainClass {
	public static void main(String[] args) {
		Host host = new Host();
		//代理角色,现在没有,需要动态生成
		ProxyInvocationHandler pih = new ProxyInvocationHandler();
		pih.setRent(host);
		//动态生成的代理对象
		Rent r = (Rent)pih.getProxy();
		r.rent(); 
	}
}

结果
在这里插入图片描述
你会发现,我们并没有写代理类,而是通过处理程序动态的生成了一个代理对象,实现了代理模式。我们发现,动态代理处理的是接口,因为他是通过接口来反射生成代理类的。这样我们一个动态代理就可以处理一类业务。大大减少了代码量,而且还降低了与目标接口的耦合程度。

三 代理模式的优点与适用场景

优点
  • 可以使真实角色的操作更加纯粹,不用关注一些公共业务
  • 公共业务交给了代理角色,实现了业务的分工
  • 公共业务发生扩展时,只需要调整代理角色,方便集中管理
  • 动态代理一个动态代理类代理的一个接口,一般就是对应一类业务。
适用场景
  • 程序可能不希望用户直接访问对象,而是提供一个特殊的对象以控制对当前对象的访问。

四 关于代理模式与装饰模式的想法

  • 在学习代理模式的时候,我常常将代理模式与装饰模式混淆,因为对于装饰模式中装饰者和被装饰者都实现同一个 接口。对代理模式来说,代理类和真实处理的类都实现同一个接口,而且两者都是对类的方法进行扩展。
  • 想了一会后,我得出了这样的结论:
    我们可以代入这样的场景:假如xx明星就是一个具体的类,我们将装饰者看作是这个明星的化妆师,将代理者看作是这个明星的经纪人。假如我们象与这个明星合作,我们需要联系经纪人,在经纪人考察过之后才能再与明星谈,而化妆师只需要将明星花里胡哨的展示在人们面前就可以了。
  • 我们专业点:
    1.装饰器模式关注于在一个对象上动态的添加方法,强调的是增强自身,在被装饰之后你能够在被增强的类上使用增强后的功能。增强后你还是你,只不过能力更强了而已
    2.代理模式关注于控制对对象的访问,为了实现对象的控制,因为被代理的对象往往难以直接获得或者是其内部不想暴露出来

这就是我所学习的代理模式,如果有什么错误或者你有更好的想法请告诉我。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值