文章目录
- 1、代理模式定义
- 2、应用场景
- 3、UML类图
- 4、通用代码实现
- 5、结果
- 6、实际例子(静态代理)
- 7、动态代理生成对象的步骤
- 8、代理模式的优缺点
- 9、静态代理和动态代理的区别
1、代理模式定义
为其他对象提供一种代理,控制对对这个对象的访问。(你去找租房子、不是直接找房东。而是通过中介所给你提供房东的信息、然后你再去找对应的房东)
2、应用场景
- 租房中介
- 婚姻介绍
- 中介找工作(打工人通过中介去电子厂打螺丝)
…
3、UML类图
- 抽象主题角色:声明真实主题和代理主题的共同接口方法
- 真实主题角色:被代理类,代表的真实对象,负责执行系统的真正的逻辑业务对象
- 代理主题角色:代理类,持有RealSubject的引用,完全具备对RealSubject的代理权
(代理中持有子类实现的父类引用,就可以调用子类的真实实现方法,而且还可以在调用该方法之前。做一些额外的事情。代码功能增强、和spirng中的aop切面有点象。比如你要结婚,婚礼的布置和婚后的收拾,交给代理类实现。你只需要去结婚就行。这个婚礼的布置和收拾就像代码功能增强)
4、通用代码实现
package com.zheng.demo4;
public class Client {
public static void main(String[] args) {
new Proxy(new RealSubject()).request();
}
//抽象主题角色
interface ISubject {
public void request();//要做的事情
}
//真实角色
static public class RealSubject implements ISubject {
@Override
public void request() {
System.out.println("我要结婚啦");
}
}
//代理角色
static class Proxy implements ISubject {
ISubject subject;
public Proxy(ISubject subject) {
this.subject = subject;
}
@Override
public void request() {
before();
subject.request();//调用真实对象的业务逻辑
after();
}
//方法增强、结婚前干的事情
public void before() {
System.out.println("布置婚礼现场");
}
//结婚后干的事情
public void after() {
System.out.println("婚礼现场的清理");
}
}
}
5、结果
6、实际例子(静态代理)
年轻人被催婚、介绍对象
代码结构
一个是静态代理、一个是动态代理。有对静态代理的改进为动态代理。
抽象
package com.zheng.demo4;
public interface IPerson {
void findLove();
}
具体的人
package com.zheng.demo4;
public class LiSi implements IPerson {
@Override
public void findLove() {
System.out.println("李四提出结婚对象的要求");
}
}
代理
package com.zheng.demo4;
public class LiSiFather implements IPerson {
LiSi liSi;
public LiSiFather(LiSi liSi) {
this.liSi = liSi;
}
@Override
public void findLove() {
liSi.findLove();
System.out.println("李四的老爹开始寻找");
System.out.println("试着交往");
}
}
客户端
package com.zheng.demo4;
public class TestClient {
public static void main(String[] args) {
new PersonProxy(new LiSi()).findLove();
}
}
结果
缺点:李四的老爹只能给李四找对象、不能给其他人找对象。
解决方法、使用动态代理、把代理类搞成一个中介、给谁都可以介绍。动态代理的底层一般不用实现,直接调用现成的API。
package com.zheng.demo4;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MeiPoProxy implements InvocationHandler {
private IPerson target;
public IPerson getInstance(IPerson target) {
this.target = target;
Class<?> clazz = target.getClass();
return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(this.target, args);
after();
return result;
}
//方法增强
public void before() {
System.out.println("我是婚姻中介所、收到了你的对象要求");
}
//方法增强
public void after() {
System.out.println("交换资料、开始交往吧");
}
}
客户端调用
package com.zheng.demo4;
public class TestClient {
public static void main(String[] args) {
new MeiPoProxy().getInstance(new LiSi()).findLove();
}
}
结果:
调用代理类的newProxyInstance
方法
进入这个方法可以看到生成一个实例对象
7、动态代理生成对象的步骤
- 1、获取被代理对象的引用,并且获取它的所有接口,反射获取
- 2、JDK动态代理类重新生成一个新的类,同时新的类要实现被代理类实现的所有接口
- 3、动态生成java代码,新加的业务逻辑方法由一定的逻辑代码调用
- 4、编译新生成的java代码.class 文件
- 5、重新加载到JVM中运行。
8、代理模式的优缺点
优点:
- 代理对象和真实对象分开
- 降低系统耦合性,扩展性好
- 保护目标对象
- 增强目标对象功能
缺点:
- 类的数量增加
- 增加代理对象,导致处理请求变慢
- 增加系统复杂度
9、静态代理和动态代理的区别
- 静态代理只能通过手动完成,被代理类增加新的方法,代理类也需要同步增加,违背开闭原则
- 动态代理采用在运行时动态生成代码,取消了对被代理类的扩展限制,遵循开闭原则
- 动态代理对目标类的增强逻辑进行扩展,结合策略模式