二十三种设计模式——代理模式

代理模式

静态代理

代理模式的场景

代理模式的两个简单场景
1、租房请添加图片描述
2、结婚请添加图片描述

代理模式角色分析

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

个人理解

个人对代理模式的理解:以租房为例
1、有个抽象类或者接口:Rent 有个抽象方法:租房
2、房东:房东要租房:实现这个接口 ,房东就可以租房了,(这我可以直接找房东租房)
3、中介:中介帮房东租房,所以中介也要实现接口或者抽象方法Rent ,中介帮房东租房,所以在中介的属性中有一个引用属性,房东,此外,中介在租房的过程中可以做租房的其他手续,比如:中介带你去看房,签订租赁合同,收中介费用

静态代理代码

Rent:

public interface Rent {
	  void rentHouse();
}

Host:

public class Host implements Rent {
	  @Override
	  public void rentHouse() {
			System.out.println("房东出租房子");
	  }
}

HostProxy:

public class HouseProxy implements Rent {
	  
	  private Host host = new Host();
	  
	  @Override
	  public void rentHouse() {
			seeHouse();
			writeProtocol();
			host.rentHouse();
			receiveProxyMoney();
	  }
	  
	  
	  private void seeHouse() {
			System.out.println("中介帶你去看房");
	  }
	  
	  private void writeProtocol() {
			System.out.println("签订租聘合同");
	  }
	  
	  private void receiveProxyMoney() {
			System.out.println("收取代理费用");
	  }
	  
	  
}

Customer

public class Customer {
	  
	  public static void main(String[] args) {
	  		// 客户找中介即可
			HouseProxy proxy = new HouseProxy();
			proxy.rentHouse();
	  }
}

代理模式的优点

1、可以使真实角色的操作更加纯粹,不用去关注一些公共的业务(房东什么都不用管,就可以租房)。
2、公共的业务也就交给代理角色!实现了业务的分工(中介租房还会可以做其他手续)。
3、公共业务发生拓展时,方便集中管理。

代理模式的缺点

一个真实的角色就会产生一个代理角色;代码量会翻倍,开发效率会变低。

使用代理模式的四大步骤

1、接口
2、真实角色
3、代理角色
4、客户端

代理模式场景:
公司给了一个任务,在实现某一个任务的前面增加一个日志,如果这个实现类有几个方法还比较好理解,那么如果实现的方法有n个呢,那么你是不是要去每个实现的方法中中写n行代码,修改原来的代码,代码量及其高,在七大原则中有一个原则:尽量不要去改变原有的代码,所以在不改变原有的代码的模式下给他做一个增强,那么使用代理模式就可以了

记住:改动原有的业务代码,在公司中是大忌
以上的模拟场景用Service和ServiceImpl来实现
静态代理可以用平常的代码就可以实现,而动态代理的话:底层都是用反射来实现的

动态代理

  • 动态代理和静态代理的角色是一样的,都是抽象类或者接口,真实角色,代理角色,客户
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    ——基于接口----------JDK动态代理【我们在这里使用】
    ——基于类------------cglib
    ——Java字节码实现—Javasist

我们先来写一个基于JDK API动态代理来理解一下动态代理:这个主要是用到了一个InvocationHandler接口,这里需要注意的是,在这个handler重写了invoke的方法,这个方法是执行这个处理器需要真正执行的方法,我们在这个方法中传入我们被代理的接口然后参数即可,这个方法会在我们获取到我们根据这个handler动态得到的代理类后调用这个代理类的方法的时候调用,如果需要扩展,我们也是在这个XXXInvocationHandler中拓展。

动态代理代码

RentInvocationHandler :

// 动态代理底层使用了反射机制
// 用这个类,自动生成代理对象
// 该类的作用:
// 1、代理谁
// 2、生成代理类
// 3、调用代理程序的一些执行方法
public class RentInvocationHandler implements InvocationHandler {
	  
	  // 被代理的接口
	  private Rent rent;
	  
	  public void setRent(Rent rent) {
	  	  this.rent = rent;
	  }
	  
	  // 生成得到代理类
	  public Rent getProxy() {
	  	  return (Rent) Proxy.newProxyInstance(this.getClass().getClassLoader(),
				  rent.getClass().getInterfaces(),this);
	  }
	  // 执行它要真正执行的方法
	  @Override
	  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	  	  	seeHouse();
			Object result = method.invoke(rent, args);
			receiveFree();
			return result;
	  }
	  
	  
	  public void seeHouse() {
			System.out.println("中介带你看房子");
	  }
	  public void receiveFree() {
			System.out.println("中介收中介费");
	  }
}

Customer:

public class Consumer {
 public static void main(String[] args) {
  // 真实角色
  Host host = new Host();
  // 代理角色不存在,找他它的处理程序去动态生成代理角色
  RentInvocationHandler proxyInvocationHandler = new RentInvocationHandler();
  proxyInvocationHandler.setRent(host); // 设置要代理的对象
  Rent proxy = proxyInvocationHandler.getProxy();
  proxy.rentHouse();
    }
  }

结果:
!https://img-blog.csdnimg.cn/40691eac579943c4bcbc1f1aa794e344.png)

接下来我们写一个万能的动态代理类
ProxyInvocationHandler:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 用这个类,自动生成代理对象
// 该类的作用:
// 1、代理谁
// 2、生成代理类
// 3、调用代理程序的一些执行方法
public class ProxyInvocationHandler implements InvocationHandler {
	  
	  // 被代理的接口
	  private Object target;
	  
	  public void setTarget(Object target) {
			this.target = target;
	  }
	  
	  // 生成得到代理类
	  public Object getProxy() {
			return Proxy.newProxyInstance(this.getClass().getClassLoader(),
					target.getClass().getInterfaces(), this);
	  }
	  
	  // 处理代理实例,并返回结果
	  @Override
	  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			Object result = method.invoke(target, args);
			return result;
	  }
}

Customer:

public class Consumer {
 public static void main(String[] args) {
  // 真实角色
  Host host = new Host();
  // 代理角色不存在,找他它的处理程序去动态生成代理角色
  ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
  proxyInvocationHandler.setTarget(host);
  Rent proxy = (Rent) proxyInvocationHandler.getProxy();
  proxy.rentHouse();
 }
}

结果:
在这里插入图片描述

使用动态代理模式的好处

  1. 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务(房东什么都不用管,就可以租房)
  2. 公共的业务也就交给代理角色!实现了业务的分工(中介租房还会可以做其他手续) 公共业务发生拓展时,方便集中管理
  3. 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  4. 一个动态代理类可以代理多个类,只要是实现了同一个接口即可

万能的动态代理工具类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class MyInvocationHandler implements InvocationHandler {
	  private Object target;
	  
	  
	  public MyInvocationHandler() {
	  }
	  
	  
	  public void setTarget(Object target) {
			this.target = target;
	  }
	  
	  
	  public Object getInstance() {
			return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	  }
	  
	  @Override
	  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			return method.invoke(target, args);
	  }
}

特定的动态代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class MySecondInvocationHandler implements InvocationHandler {
	  
	  
	  private Rent rent;
	  
	  
	  public MySecondInvocationHandler() {
	  }
	  
	  
	  public void setRent(Rent rent) {
			this.rent = rent;
	  }
	  
	  
	  public Rent getProxy() {
			return (Rent) Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
	  }
	  
	  @Override
	  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			return method.invoke(rent, args);
			
			
	  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值