当前位置: 首页 > news >正文

设计模式之代理模式

什么是代理模式?

代码仓库地址: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思想么?

相关文章:

  • 【运维笔记】Centos 7.5 安装 Docker详细步骤
  • 光伏发电预测(LSTM、CNN_LSTM和XGBoost回归模型,Python代码)
  • uniapp echarts 适配H5与微信小程序
  • 传统机器学习聚类算法——总集篇
  • kafka简易搭建(windows环境)
  • 使用postman 调用 Webservice 接口
  • Vue中如何进行数据可视化雷达图展示
  • 八大排序java
  • 阿里测试师用UI自动化测试实现元素定位!
  • 微服务技术栈-Gateway服务网关
  • Git 学习笔记 | Git 基本理论
  • H5+Css3文本溢出添加省略号(包括插件)
  • 【用unity实现100个游戏之14】Unity2d做一个建造与防御类rts游戏
  • 这7个AI软件让设计效率飞起,快来收藏 优漫动游
  • windows C 开发
  • freertos信号量之二值信号量
  • C++ - 右值引用 和 移动拷贝
  • NPM 常用命令(九)
  • Java中栈实现怎么选?Stack、Deque、ArrayDeque、LinkedList(含常用Api积累)
  • Docker 日志管理 - ELK
  • 上海杨浦:鼓励龙头企业与高校共建创新联合体,最高支持200万元
  • 张笑宇:物质极大丰富之后,我们该怎么办?
  • 减重人生|走过节食弯路,她如何半年减60斤找回自信?
  • 普京提议恢复直接谈判,泽连斯基:望俄明日停火,乌愿谈判
  • 重庆一高校75万采购市价299元产品?工作人员:正在处理
  • 同济大学原常务副校长、著名隧道及地下工程专家李永盛逝世