写点什么

【设计模式】代理模式,java 面试官常问的问题

用户头像
极客good
关注
发布于: 刚刚

/**


  • @ProjectName: demo

  • @Package: com.ymy.proxy

  • @ClassName: IUserService

  • @Author: 流星 007

  • @Description: user interface

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/8/29 15:26

  • @Version: 1.0


*/


public interface IUserService {


Boolean login(String username,String password);


}


package com.ymy.proxy;


/**


  • @ProjectName: demo

  • @Package: com.ymy.proxy

  • @ClassName: UserService

  • @Author: 流星 007

  • @Description: user login or register

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/8/29 15:10

  • @Version: 1.0


*/


public class UserService implements IUserService{


/**


  • login in

  • @param username

  • @param password


*/


@Override


public Boolean login(String username,String password){


System.out.println("username:"+username);


System.out.println("password:"+password);


return true;


}


}


package com.ymy.proxy;


/**


  • @ProjectName: demo

  • @Package: com.ymy.proxy

  • @ClassName: UserServiceProxy

  • @Author: 流星 007

  • @Description: user proxy

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/8/29 15:29

  • @Version: 1.0


*/


public class UserServiceProxy implements IUserService{


private UserService userService;


public UserServiceProxy(UserService userService) {


this.userService = userService;


}


@Override


public Boolean login(String username, String password) {


long startTime = System.currentTimeMillis();


Boolean login = userService.login(username, password);


long endTime = System.currentTimeMillis();


System.out.println("login time : " + (endTime - startTime) +" ms" );


return login;


}


}


package com.ymy.proxy;


/**


  • @ProjectName: demo

  • @Package: com.ymy.proxy

  • @ClassName: Test

  • @Author: 流星 007

  • @Description: test

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/8/29 15:15

  • @Version: 1.0


*/


public class Test {


public static void main(String[] args) {


UserServiceProxy userServiceProxy = new UserServiceProxy(new UserService());


Boolean login = userServiceProxy.login("zhgnsan", "123456");


System.out.println("login result : " +login);


}


}


这就是基于组合模式实现的静态代理,代理类和被代理类同时实现一个 IUserService 接口,代理类中的 login 方法去调用被代理类中的 login 方法,这样需要稍微改动一下被代理类,让他们去实现同一个接口。


[](


)组合与继承如何选择


========================================================================


静态代理的实现方式相信大家也应该知道怎么实现了,那什么时候实现组合,什么时候使用继承呢?不知道大家有没有听过这么一句话:组合优于继承;能使用组合就少使用继承,原因是继承的层数过大时维护和扩展会非常难受,但是也不绝对,相对于代理模式而言,如果被代理的类来源于第三方,你无法改动原类,那么继承将是一个不错的原则,一般情况下,我还是推荐组合的这种方式。



[](


)动态代理


===================================================================


静态代理是说完了,还有一种代理模式不知道大家听过没有,那就是动态代理模式,如果熟悉 java aop 的都应该对 java 的动态代理不会陌生,那我们现在来讲讲什么是动态代理。


不知道大家思考过一个问题没有,你们觉得静态代理有什么缺点吗?



可能大家想到了,如果被代理的类过多,成千上百的话,代理类也要成千上百,大大增加了程序员的工作量,他们都是差不多的一个模板,难道就不能只写一次,符合所有的被代理类吗?


当然可以,这个时候动态代理就出现了,动态代理:就是我们不需要在程序运行前为被代理类创建代理类,而是在程序运行中,动态的创建代理类,然后使用这些动态生成的代理类替代原始类,是不是就省去了大量的编码时间?那如何实现呢?


下面请看我表演


package com.ymy.proxy;


/**


  • @ProjectName: demo

  • @Package: com.ymy.proxy

  • @ClassName: IUserService

  • @Author: 流星 007

  • @Description: user interface

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/8/29 15:26

  • @Version: 1.0


*/


public interface IUserService {


Boolean login(String username,String password);


}


package com.ymy.proxy;


import org.springframework.cglib.proxy.InvocationHandler;


import org.springframework.cglib.proxy.Proxy;


import java.lang.reflect.Method;


/**


  • @ProjectName: demo

  • @Package: com.ymy.proxy

  • @ClassName: dynamicUserUserProxy

  • @Author: 流星 007

  • @Description: dynamic User proxy

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/8/30 13:33

  • @Version: 1.0


*/


public class DynamicUserUserProxy {


public Object createProxy(Object object) {


Class[] interfaces = object.getClass().getInterfaces();


DynamicProxyHandler handler = new DynamicProxyHandler(object);


return Proxy.newProxyInstance(object.getClass().getClassLoader(), interfaces, handler);


}


private class DynamicProxyHandler implements InvocationHandler {


private Object object;


public DynamicProxyHandler(Object object) {


this.object = object;


}


@Override


public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {


long startTime = System.currentTimeMillis();


Object result = method.invoke(object, args);


long endTime = System.currentTimeMillis();


System.out.println("login time : " + (endTime - startTime) +" ms" );


return result;


}


}


}


package com.ymy.proxy;


/**


  • @ProjectName: demo

  • @Package: com.ymy.proxy

  • @ClassName: DynamicTest

  • @Author: 流星 007

  • @Description: Dynamic Test

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/8/30 13:36

  • @Version: 1.0


*/


public class DynamicTest {


public static void main(String[] args) {


DynamicUserUserProxy proxy = new DynamicUserUserProxy();


IUserService userService = (IUserService) proxy.createProxy(new UserService());


Boolean login = userService.login("zhangsan", "123456");


System.out.println("login result :" +login);


}


}


username:zhangsan


password:123456


login time : 0 ms


login result :true


Process finished with exit code 0


我这里实现动态代理是基于 cglib,由静态代理改成动态代理之后是不是觉得干净多了,如果后续还有类需要代理,就不需要在创建代理类了,让程序在运行中自己创建,简直不要太爽。


[](


)代理模式应用场景


=======================================================================


1.日志、鉴权、限流、统计等物业功能的开发。


2.rpc 远程调用。


3.一个类需要做扩展功能的时候。


[](


)总结


=================================================================


什么是代理模式?,就是在不改变原类的情况下新增新的功能,比如日志、流量监控、请求耗时等等操作都可以通过代理模式来解决。


代理模式分为静态代理和动态代理,静态代理可以通过继承和组合实现,动态代理可以通过 cglib 和 jdk 自带的动态代理实现,如果在日常开发过程中,你想要做一些扩展功能,比如:日志、鉴权等,那么就可以考虑一下代理模式哦。



推荐文章:


[【设计模式】单例模式](


)


[【设计模式】工厂模式:你还在使用一堆的 if/else 创建对象吗?](


)


[【设计模式】建造者模式:你创建对象的方式有它丝滑吗?](


)


[【设计模式】原型模式


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


:如何快速的克隆出一个对象?](


)


[【设计模式】策略模式:我是一个有谋略的类](


)


[【设计模式】观察者模式:一个注册功能也能使用到设计模式?](


)[【设计模式】门面模式:接口就像门面,一眼就能看出你的代码水平](


)

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
【设计模式】代理模式,java面试官常问的问题