

结构型设计模式之代理模式_积跬步,至千里。的技术博客_51CTO博客
source link: https://blog.51cto.com/u_13494008/5576774
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

结构型设计模式之代理模式
原创结构型设计模式之代理模式
代理模式(Proxy Pattern)属于结构型模式。
它是指为其他对象提供一种代理以控制对这个对象的访问。
在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
在代理模式中,创建具有现有对象的对象,以便向外界提供功能接口。
想在访问一个类时做一些控制的时候就可以是用代理模式。
代理模式属于结构型模式,分为静态代理和动态代理。
1.静态代理:静态定义代理类
静态代理需要自己生成代理类
2.动态代理:动态生成代理类
动态代理不用亲自去实现,通常使用现成的API即可。目前普遍使用的是JDK自带的代理与CGLIB提供的类库。
代理模式一般包含三种角色:
1.抽象主题角色(Subject)
抽象主题类的主要职责是声明真实主题与代理的共同接口方法,该类可以是接口也可以是抽象类
2.真实主题角色(RealSubject)
该类也被称为被代理类,该类定义了代理所表示的真实对象,是负责执行系统真正的罗辑业务对象
3.代理主题角色(Proxy)
代理主题也被称为代理类,其内部特有RealSubject的引用,因此具备完全的对RealSubject的代理权。
客户端调用代理对象的方法,同时也调用被代理对象的方法,但是会在代理对象前后增加一些处理代码。可以理解为代码增强,实际上就是在原代码罗辑前后增加一些代码逻辑,而使调用者无感知。
1.保护目标对象,将代理对象与真实被调用目标对象分离
2.增强目标对象
3.降低系统耦合性,提升扩展性
静态代理与动态代理的区别
1.静态代理只能通过手动完成代理操作,如果被代理类增加了新的方法,代理类需要同步增加,违背开闭原则。
2.动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原测。
3.若动态代理要对目标类的增强逻辑进行扩展,结合策略模式,只需要新增策略类便可完成,无须修改代理类的代码。
静态代理的基本使用
静态代理需要自己生成代理类
创建抽象主题
public interface ISubject {
/**
* 买票
*/
void buyTickets();
}
创建真实主题
public class RealSubject implements ISubject {
public void buyTickets() {
System.out.println("进行买票操作");
}
}
创建代理主题
public class Proxy implements ISubject {
private ISubject subject;
public Proxy(ISubject subject) {
this.subject = subject;
}
public void buyTickets() {
before();
subject.buyTickets();
after();
}
public void before() {
System.out.println("买票前的操作");
}
public void after() {
System.out.println("买票后的操作");
}
}
客户端调用
public static void main(String[] args) {
Proxy proxy = new Proxy(new RealSubject());
proxy.buyTickets();
}
买票前的操作
进行买票操作
买票后的操作
JDK动态代理的基本使用
创建抽象主题
public interface IUser {
/**
* 购物
*/
void shopping();
}
创建真实主题
public class User implements IUser{
@Override
public void shopping() {
System.out.println("user shopping....");
}
}
创建代理主题
public class JDKProxy implements InvocationHandler {
private Object tarjet;
public JDKProxy(Object tarjet) {
this.tarjet = tarjet;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理user,执行shopping()开始...");
Object oj = method.invoke(tarjet, args);
System.out.println("代理user,执行shopping()结束...");
return oj;
}
}
客户端调用
public static void main(String[] args) {
User user = new User();
JDKProxy jdkProxy = new JDKProxy(user);
IUser proxyInstance = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), jdkProxy);
proxyInstance.shopping();
}
代理user,执行shopping()开始...
user shopping....
代理user,执行shopping()结束...
在调用时候,传入了一推参数,可进一步优化
public class JDKProxy implements InvocationHandler {
private Object tarjet;
public Object JDKProxy(Object target){
this.tarjet = target;
Class<?> clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理user,执行shopping()开始...");
Object oj = method.invoke(tarjet, args);
System.out.println("代理user,执行shopping()结束...");
return oj;
}
}
public static void main(String[] args) {
JDKProxy jdkProxy = new JDKProxy();
IUser user= (IUser)jdkProxy.JDKProxy(new User());
user.shopping();
}
CGLIB动态代理的基本使用
CGLIB动态代理也不需要生成代理类,实现MethodInterceptor 就可以了。
注意:CGLib不能代理final的方法
创建抽象主题
注意:CGLb代理的目标对象不需要实现任何接口,就可以通过动态继承目标对象实现动态代理。
所以此处可以不用创建接口。直接使用真实主题。
public interface IUser {
public void shopping();
}
创建真实主题
public class User implements IUser{
@Override
public void shopping() {
System.out.println("user shopping....");
}
}
直接使用真实主题。
public class User {
public void shopping() {
System.out.println("user shopping....");
}
}
创建代理主题
public class CglibProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理user,执行shopping()开始...");
Object invokeSuper = methodProxy.invokeSuper(o, objects);
System.out.println("代理user,执行shopping()结束...");
return invokeSuper;
}
}
客户端调用
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(User.class);
enhancer.setCallback(cglibProxy);
IUser iUser = (IUser) enhancer.create();
iUser.shopping();
}
在客户端调用时,稍显复杂,可进一步优化
public class CglibProxy implements MethodInterceptor {
public Object getInstance(Class<?> clazz) throws Exception{
//相当于Proxy,代理工具类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理user,执行shopping()开始...");
Object invokeSuper = methodProxy.invokeSuper(o, objects);
System.out.println("代理user,执行shopping()结束...");
return invokeSuper;
}
}
public static void main(String[] args) throws Exception {
IUser user = (IUser) new CglibProxy().getInstance(User.class);
user.shopping();
}
CGLIB与JDK动态代理区别
1.执行条件
JDK动态代理实现了被代理对象的接口。CGLb代理的目标对象不需要实现任何接口,它是通过动态继承目标对象实现动态代理。
2.实现机制
JDK动态代理调用代理方法是由Java内部的反射机制来实现的,需要读取接口信息。CGLib动态代理是通过FastClass机制来实现的,需要覆盖父类方法。
首先都在运行期生成字节码。
JDK动态代理的代理逻辑简单,直接写Class字节码,使用反射机制在生成类的过程中比较高效。
CGLib代理实现更复杂,使用ASM框架写Class字节码,但是asm在生成类之后的相关执行过程中比较高效。但是可以通过将asm生成的类进行缓存,解决asm生成类过程低效问题。
一句话:CGLib生成代理类比JDK动态代理效率低,但是执行效率比JDK动态代理高。
Recommend
-
76
代理模式(Proxy): 代理模式就是给某一个对象提供一个代理,并由代理对象控制对原有对象的引用。在一些情况下,一个客户不想或者不能直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。例如windows桌面...
-
32
今天要开始我们 结构型 设计模式的学习,设计模式源于生活,还是希望能通过生活中的一些小栗子去理解学习它,而不是为了学习而学习这些东西。 结构型设计模式 结构型设计模式又分为 类...
-
3
积跬步至千里:QUIC 协议在蚂蚁集团落地之综述 作者:孔令涛 自 2015 年以来,QUIC 协议开始在 IETF 进行标准化并被国内外各大厂商相继落地。鉴于 QUIC 具备“0RTT 建联”、“支持连接迁移”等诸多优势,并将成为下一代互联网协议:...
-
8
结构性设计模式之门面模式 推荐 原创 结构性设计模式之门面模式 门面模式(Facade Pattern)又叫外观模...
-
7
结构型设计模式之享元模式 推荐 原创 享元模式(Flyweight Pattern)又称为轻量级模式,是对象池的一种实现。属于结构型...
-
4
结构型设计模式之桥接模式 精选 原创 结构型设计模式之桥接模式
-
6
行为型设计模式之模板方法模式模板方法模式 模板方法模式(Template Method Pattern)属于行为型设计模式。 它是指定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子...
-
9
创建型设计模式之建造者模式 精选 原创 丨Jack_Chen丨 2022-08-30 21:19:44
-
5
访问者模式 访问者模式属于行为型模式。它是一种将数据结构与数据操作分离的设计模式。是指封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
-
4
设计模式(十六)----结构型模式之代理享元模式 ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK