设计模式——代理模式

shigen坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。 个人IP:shigen

最近在学习的时候,突然看到了代理模式。一看就很熟悉,因为在spring中大量用到了代理模式。那接下来将结合查询到的资料和代码,分享一下代理模式的分类和实现,以及golang版本的。

先来看下代理模式的类图,拒绝乱七八糟的文字

很简单,就是在一个接口的实现类方法处理逻辑中执行其他的逻辑。一分析,重点来了!如何获得接口实现类方法

静态代理

很简单的一种方式就是我再写一个类,直接把原有的方法调用一遍,不同的是我现在混杂了新逻辑,三方使用的话,也是调用我的新代码逻辑。

相信接下来的代码大家一看就明白,我就直接贴上代码了:

java实现

同样我们改造一下,就是go的实现:

go版本

go 复制代码
 import "fmt"
 ​
 // Subject 接口定义了需要被代理的对象的方法
 type Subject interface {
   Request() string
 }
 ​
 // RealSubject 是需要被代理的对象
 type RealSubject struct{}
 ​
 func (r *RealSubject) Request() string {
   return "RealSubject: 处理请求"
 }
 ​
 // Proxy 是代理对象,它包含了一个指向 RealSubject 的引用
 type Proxy struct {
   realSubject *RealSubject
 }
 ​
 func (p *Proxy) Request() string {
   // 在这里可以进行一些额外的操作,例如鉴权、日志等
   result := "Proxy: 转发请求到 RealSubject\n"
   if p.realSubject == nil {
     p.realSubject = &RealSubject{}
   }
   result += " " + p.realSubject.Request()
   return result
 }
 ​
 // 使用代理模式来使用 RealSubject 对象
 func main() {
   // proxy := &Proxy{}
   // fmt.Println(proxy.Request())
 ​
   realSubject := &RealSubject{}
   fmt.Println(realSubject.Request())
 }

注:代码和文章参考:

动态代理

官方一点的话术是这样的:由于静态代理只能够对一种类型(接口)进行代理,如果想要对多种类型进行代理的话就需要创建多个代理类,为了弥补了静态代理的不足,从而出现了动态代理,使用反射技术实现。

我直接表示看不懂,直呼看不懂。

来点简单的,我直接放代码吧:

关键点在于我的Proxyfactory:

typescript 复制代码
 public class ProxyFactory {
 ​
     public <T> SmsService getProxyObject(T target) {
         /**
          * ClassLoader loader, 类加载器,加载代理类
          * Class<?>[] interfaces, 真实对象实现接口
          * InvocationHandler h 代理对象处理的函数
          */
         if (target instanceof SmsService) {
             return (SmsService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
                 @Override
                 public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                     System.out.println("开始代理");
                     Object result = method.invoke(target, objects);
                     System.out.println("代理结束");
                     return result;
                 }
             });
         } else {
             throw new IllegalArgumentException("Target object must implement the specified interface");
         }
     }
 ​
 }

函数的参数target就是需要代理的对象。这里可以封装成一个统一的工具类,先不做展示了。

代码的调用方面:

ini 复制代码
 public class MainMethod {
 ​
     public static void main(String[] args) {
         // 生成新对象
         PhoneSmsService phoneSmsService = new PhoneSmsService();
         PcSmsService pcSmsService = new PcSmsService();
 ​
         ProxyFactory proxyFactory = new ProxyFactory();
         SmsService PhoneProxyObject = proxyFactory.getProxyObject(phoneSmsService);
         SmsService pcProxyObject = proxyFactory.getProxyObject(pcSmsService);
 ​
         PhoneProxyObject.send();
         pcProxyObject.send();
     }
 ​
 }

运行结果:

所以对比之下,动态代理的优点就很明显了:

  1. 简化开发:相比静态代理,动态代理可以减少重复代码;
  2. 更灵活:动态代理可以在运行时动态地创建代理对象,可以应用于更广泛的场景。

在此,设计模式的学习+1。

与shigen一起,每天不一样!

相关推荐
free-9d2 小时前
NodeJs后端常用三方库汇总
后端·node.js
写不出来就跑路3 小时前
WebClient与HTTPInterface远程调用对比
java·开发语言·后端·spring·springboot
天上掉下来个程小白4 小时前
MybatisPlus-06.核心功能-自定义SQL
java·spring boot·后端·sql·微服务·mybatisplus
知了一笑4 小时前
独立开发第二周:构建、执行、规划
java·前端·后端
寻月隐君4 小时前
想用 Rust 开发游戏?这份超详细的入门教程请收好!
后端·rust·github
晴空月明5 小时前
分布式系统高可用性设计 - 缓存策略与数据同步机制
后端
Real_man6 小时前
新物种与新法则:AI重塑开发与产品未来
前端·后端·面试
小马爱打代码6 小时前
Spring Boot:将应用部署到Kubernetes的完整指南
spring boot·后端·kubernetes
卜锦元6 小时前
Go中使用wire进行统一依赖注入管理
开发语言·后端·golang
SoniaChen338 小时前
Rust基础-part3-函数
开发语言·后端·rust