前言:学习自https://www.bilibili.com/video/BV1WE411d7Dv?p=19
文章目录
代理模式
静态代理模式
1、介绍
1、真实角色和代理角色要实现同一个接口
2、代理角色要代理真实角色
3、给代理角色添加set方法(属性为接口,从而解耦合),将某个真实角色注入到代理角色的属性中,以便调用
2、例子:婚介公司
public class StaticProxyTest {
public static void main(String[] args) {
You you = new You();
WeddingCompany weddingCompany = new WeddingCompany();
weddingCompany.setMarry(you);
/*
这也是多线程Thread的原理
new Thread(一个实现Runnable接口的类).start(),而且Thread本身也实现了Runnable接口
*/
weddingCompany.HappyMarry();
}
}
interface Marry {
void HappyMarry();
}
//真实角色,你去结婚
class You implements Marry {
@Override
public void HappyMarry() {
System.out.println("Marry~");
}
}
//代理角色,帮你结婚
class WeddingCompany implements Marry {
private Marry target;
public void setMarry(Marry target) {
//传入真实角色
this.target = target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry(); //真实角色
after();
}
private void before() {
System.out.println("before--arrangement~");
}
private void after() {
System.out.println("after--clear~");
}
}
3、优点
代理角色可以做真实角色分外的事,从而真实角色专注做自己分内的事
动态代理模式
1、介绍
- 动态代理的角色和静态代理的一样
- 动态代理的代理类是动态生成的,静态代理的代理类是我们提前写好的
- 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
(1)基于接口的动态代理----JDK动态代理
(2)基于类的动态代理----cglib
(3)现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist
JDK的动态代理需要了解两个类:
-
InvocationHandler
-
Proxy
2、例子:租房中介公司
public class DynamicProxyTest {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理实例的调用处理程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setRent(host); //将真实角色放置进去!
Rent proxy = (Rent)pih.getProxy(); //动态生成对应的代理类!
proxy.rent();
}
}
//接口
interface Rent {
public void rent();
}
//真实角色: 房东,房东要出租房子
class Host implements Rent{
public void rent() {
System.out.println("房屋出租");
}
}
//代理角色:中介
class ProxyInvocationHandler implements InvocationHandler {
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
// proxy : 代理类 method : 代理类的调用处理程序的方法对象.
// 处理代理实例上的方法调用并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
//核心:本质利用反射实现!
Object result = method.invoke(rent, args);
fare();
return result;
}
//看房
public void seeHouse(){
System.out.println("带房客看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
更有普适性的例子(优化了 ProxyInvocationHandler 类):
public class DynamicProxyTest {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(host); //将真实角色放置进去!
Rent proxy = (Rent)pih.getProxy(); //动态生成对应的代理类!
proxy.rent();
}
}
//接口
interface Rent {
public void rent();
}
//真实角色: 房东,房东要出租房子
class Host implements Rent{
public void rent() {
System.out.println("房屋出租");
}
}
//代理角色:中介
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);
}
// proxy : 代理类
// method : 代理类的调用处理程序的方法对象.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
public void log(String methodName){
System.out.println("执行了"+methodName+"方法");
}
}
3、优点
(包含了静态代理的优点)
- 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情
- 公共的业务由代理来完成 . 实现了业务的分工
- 公共业务发生扩展时变得更加集中和方便
- 一个动态代理 , 一般代理某一类业务
- 一个动态代理可以代理多个类,代理的是接口