什么是代理模式?
代码仓库地址:https://github.com/fineCoderWithLove/algorithmandDesignpattern
做一个简单的形象的例子吧,就好比师傅想要化缘,但是师傅心高气傲又怎么肯?于是师傅把碗给了二师兄,于是二师兄就成了一个代理对象,由代理对象来执行化缘的过程。下面博主来一步步介绍如何进行代理的设计以及代理的思路。
- 首先要进行代理,我们来分析,很显然师傅和二师兄都要有一个化缘的方法,这样二师兄才能够去代理师傅化缘,但是他又用的师傅的碗,显然被代理和代理对象都要实现同一个接口才行
- 其次师傅还要又证明自己身份的碗,所以被代理对象要有自己的属性,来表示这个事情是我名义上做的。
下面来看以下Java代码的实现
以经济公司代理歌手来实现,歌手不会参与卖票,租场地之类的活,只会进行表演,所以累活全部由经济公司承担。
1. 定义接口
package com.设计模式.代理模式;
/**
* Created with IntelliJ IDEA.
*
* @Author: Coderfine
* @Date: 2023/10/01/21:50
* @Description:
*/
public interface Star {
String sing(String name);
void dance();
}
2. 定义BigStar类
package com.设计模式.代理模式;
/**
* Created with IntelliJ IDEA.
*
* @Author: Coderfine
* @Date: 2023/10/01/21:47
* @Description:被代理的对象
*/
public class BigStar implements Star{
private String name;
public BigStar(String name) {
this.name = name;
}
public String sing(String name){
System.out.println(this.name+"正在唱"+name);
return "谢谢";
}
public void dance(){
System.out.println(this.name+"正在跳舞iu");
}
}
3 生成一个代理对象
package com.设计模式.代理模式;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created with IntelliJ IDEA.
*
* @Author: Coderfine
* @Date: 2023/10/01/21:52
* @Description:
*/
public class ProxyUtil {
public static Star createProxy(BigStar bigStar) {
Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{
Star.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//待理对象要做的事情
if (method.getName().equals("sing")) {
System.out.println("待理对象开始收钱了");
return method.invoke(bigStar, args);
}else if(method.getName().equals("dance")){
System.out.println("待理对象开始准备场地了");
return method.invoke(bigStar, args); //这一块实际上就是执行业务的代码
}else {
return method.invoke(bigStar, args);
}
}
});
return starProxy;
}
}
三个参数分别是(写法基本固定)
- 类名.class.getClassLoader()
- new Class[]{Star.class}
- 一个匿名内部类
内部的method.invoke(bigStar, args);方法实际上就是执行的业务逻辑。学过spring的同学可以思考以下这不就是AOP的思想么?
4.测试
package com.设计模式.代理模式;
/**
* Created with IntelliJ IDEA.
*
* @Author: Coderfine
* @Date: 2023/10/01/22:00
* @Description:这是一个代理模式
*/
public class Test {
public static void main(String[] args) {
BigStar cxk = new BigStar("蔡徐坤");
//创建待理对象
Star proxy = ProxyUtil.createProxy(cxk);
System.out.println(proxy.sing("只因你太美"));
proxy.dance();
}
}
测试结果如下
待理对象开始收钱了
蔡徐坤正在唱只因你太美
谢谢
待理对象开始准备场地了
蔡徐坤正在跳舞iu
那么大家就会问,这种应用场景是什么呢?
下面来给大家模拟以下
二师兄写的几个方法要进行代码的耗时统计,他在每个接口都写了这个公共模块
new begintime;
new endtime;
sout(endtime-begintime);
void Login(String name,String password){
new begintime;
if(name == "admin" && password =="123456"){
sout("success");
new endtime;
sout(endtime-begintime);
}
}
void SelectInfo(String name){
new begintime;
SelectUserInfo(name);
new endtime;
sout(endtime-begintime);
}
}
void DeleteUsers(String[] usersId){
new begintime;
DeleteUsersById(users);
new endtime;
sout(endtime-begintime);
}
}
细心的大师兄肯定会发现很多地方有冗余,所以完全可以创建一个代理对象然后然后代理对象去统计耗时的问题,这样代码就会简洁多了。
package com.设计模式.代理模式;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created with IntelliJ IDEA.
*
* @Author: Coderfine
* @Date: 2023/10/01/21:52
* @Description:
*/
public class ProxyUtil {
public static Star createProxy(BigStar bigStar) {
Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{
Star.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//待理对象要做的事情
if (method.getName().equals("sing")) {
new begintime;
return method.invoke(bigStar, args);
new endtime;
sout(endtime-begintime);
}else if(method.getName().equals("dance")){
new begintime;
return method.invoke(bigStar, args); //这一块实际上就是执行业务的代码
new endtime;
sout(endtime-begintime);
}else {
return method.invoke(bigStar, args);
}
}
});
return starProxy;
}
}
这样做代码不是就被优化成这样了么
void Login(String name,String password){
if(name == "admin" && password =="123456"){
sout("success");
}
}
void SelectInfo(String name){
SelectUserInfo(name);
}
}
void DeleteUsers(String[] usersId){
DeleteUsersById(users);
}
}
这样业务明显就被简化了,很大程度上减少了代码的冗余,这不就是Spring的AOP思想么?