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

设计模式 结构型 代理模式(Proxy Pattern)与 常见技术框架应用 解析

在这里插入图片描述

代理模式(Proxy Pattern)是一种常见的设计模式,在软件开发中有着广泛的应用。其核心思想是通过创建一个代理类来控制对另一个对象的访问,从而实现对目标对象功能的扩展、保护或其他附加操作。

一、核心思想

代理模式的核心思想在于提供一个代理对象,作为客户端与目标对象之间的中介。客户端并不直接调用目标对象的方法,而是通过调用代理对象的方法来间接调用目标对象的方法。这样可以在调用目标对象方法之前或之后添加额外的逻辑,如权限检查、日志记录、事务处理等。

二、定义与结构

定义:代理模式为其他对象提供一种代理以控制对这个对象的访问。

结构

  • 抽象角色(Subject):通过接口或抽象类声明真实角色实现的业务方法。
  • 代理角色(Proxy):实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
  • 真实角色(Real Subject):实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

角色

在代理模式中,通常涉及以下三个角色:

  • 抽象主题(Subject):定义了真实主题和代理主题的共同接口。
  • 真实主题(Real Subject):实现了具体的业务逻辑,是代理模式中被代理的对象。
  • 代理主题(Proxy Subject):持有对真实主题的引用,可以在调用真实主题之前或之后执行附加的操作。

三、实现步骤及代码示例

以下是通过Java技术框架实现代理模式的详细步骤及代码示例:

静态代理

  1. 定义抽象主题接口:
public interface Subject {
    void request();
}
  1. 实现真实主题类:
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}
  1. 实现代理主题类:
public class ProxySubject implements Subject {
    private RealSubject realSubject;

    @Override
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.request();
        postRequest();
    }

    private void preRequest() {
        System.out.println("ProxySubject: Preparing for request.");
    }

    private void postRequest() {
        System.out.println("ProxySubject: Finishing up request.");
    }
}
  1. 客户端代码:
public class Client {
    public static void main(String[] args) {
        Subject subject = new ProxySubject();
        subject.request();
    }
}

动态代理

  1. 定义抽象主题接口(同上)。
  2. 实现真实主题类(同上)。
  3. 创建InvocationHandler实现类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxyHandler implements InvocationHandler {
    private final Object target;

    public ProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        preRequest();
        Object result = method.invoke(target, args);
        postRequest();
        return result;
    }

    private void preRequest() {
        System.out.println("ProxySubject: Preparing for request.");
    }

    private void postRequest() {
        System.out.println("ProxySubject: Finishing up request.");
    }
}
  1. 客户端代码:
import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        InvocationHandler handler = new ProxyHandler(realSubject);
        Subject subject = (Subject) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                handler
        );
        subject.request();
    }
}

四、常见技术框架应用

1、网络请求代理服务器

在网络请求中,可能会使用代理服务器。假设我们有一个简单的网络请求接口和实现:

  • 定义抽象主题(网络请求接口):
interface NetworkRequest {
    String request(String url);
}
  • 真实主题(实际的网络请求实现):
class RealNetworkRequest implements NetworkRequest {
    @Override
    public String request(String url) {
        System.out.println("Sending request to " + url);
        // 这里可以是实际的网络请求代码,比如使用HttpURLConnection等
        return "Response from " + url;
    }
}
  • 代理(带有缓存功能的网络请求代理):
import java.util.HashMap;
import java.util.Map;

class CachedNetworkRequestProxy implements NetworkRequest {
    private RealNetworkRequest realRequest;
    private Map<String, String> cache = new HashMap<>();

    @Override
    public String request(String url) {
        if (cache.containsKey(url)) {
            System.out.println("Retrieving from cache for " + url);
            return cache.get(url);
        } else {
            if (realRequest == null) {
                realRequest = new RealNetworkRequest();
            }
            String response = realRequest.request(url);
            cache.put(url, response);
            return response;
        }
    }
}
  • 使用示例:
NetworkRequest request = new CachedNetworkRequestProxy();
System.out.println(request.request("https://example.com"));
System.out.println(request.request("https://example.com"));

这里代理对象CachedNetworkRequestProxy在第一次请求时会调用真实对象RealNetworkRequest进行网络请求,然后将结果缓存起来。之后相同的请求就直接从缓存中获取,减少了网络请求的次数。

2、Spring AOP

在Java中,代理模式也很常见,特别是在Spring框架中。以下是一个简单的Spring AOP(面向切面编程)示例:

import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;

// Service interface
public interface SimpleService {
    void perform();
}

// Service implementation
public class SimpleServiceImpl implements SimpleService {
    @Override
    public void perform() {
        System.out.println("Performing service operation");
    }
}

// Before advice
public class LoggingBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Logging before method: " + method.getName());
    }
}

// Client code
public class ProxyDemo {
    public static void main(String[] args) {
        SimpleService service = new SimpleServiceImpl();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(service);
        factory.addAdvice(new LoggingBeforeAdvice());
        
        SimpleService proxy = (SimpleService) factory.getProxy();
        proxy.perform(); // Output: Logging before method: perform \n Performing service operation
    }
}

在这个例子中,ProxyFactory创建了一个代理对象,并在方法调用之前添加了日志记录功能。

在Java中,代理模式通常用于远程方法调用(RMI)、JDK动态代理或CGLIB代理。在.NET中,可以用Castle DynamicProxy库来创建代理。而在Python中,wrapt库提供了强大的装饰器和代理功能。在C#中,可以使用RealProxy类来实现动态代理。这些技术框架中的代理模式实现方式虽然有所不同,但核心思想都是相同的,即通过代理对象来控制对目标对象的访问。

五、应用场景

代理模式的应用场景非常广泛,包括但不限于以下几个方面:

  1. 远程代理:为其他对象提供一种代理以控制对这个对象的远程访问。例如,在分布式系统中,客户端可以通过代理对象来访问远程服务器上的对象。
  2. 虚拟代理:根据需要创建开销很大的对象。在真实对象创建之前,虚拟代理对象可以充当其代理。例如,在加载大型图片或视频时,可以先显示一个占位符或缩略图,待图片或视频加载完成后再显示真实内容。
  3. 安全代理:控制对资源的访问权限。例如,在Web应用中,可以通过代理对象来检查用户是否具有访问某个资源的权限。
  4. 智能代理:当调用真实对象时,代理对象可以附加一些额外的处理逻辑。例如,在调用数据库查询方法之前,代理对象可以自动添加分页、排序等处理逻辑。

六、优缺点

优点

  1. 中介作用:代理对象可以在客户端和目标对象之间起到中介的作用,从而保护目标对象。
  2. 功能扩展:代理对象可以扩展目标对象的功能,而不需要修改目标对象的代码。
  3. 降低耦合度:代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性。

缺点

  1. 类数量增加:代理模式会造成系统设计中类的数量增加,从而增加了系统的复杂度。
  2. 请求处理变慢:在客户端和目标对象之间增加一个代理对象,可能会造成请求处理速度变慢。

综上所述,代理模式是一种非常有用的设计模式,它可以在不修改目标对象代码的前提下,实现对目标对象功能的扩展和保护。同时,代理模式也具有一定的缺点,需要在具体应用场景中进行权衡和选择。

在这里插入图片描述


http://www.kler.cn/a/465428.html

相关文章:

  • GROUP BY 的目的是将数据按照指定的列进行分组,然后对每个分组进行聚合计算,分组后,每个分组只会返回一行结果。
  • Python 3 与 Python 2 的主要区别
  • 微服务之服务治理——Eureka
  • python-leetcode-买卖股票的最佳时机 II
  • 基于XGBoost算法的集成学习
  • linux网络管理
  • 特征值描述了系统的固有频率平方,而特征向量描述了系统的振动模式
  • throw与noexcept对比
  • AI赋能跨境电商:魔珐科技3D数字人破解出海痛点
  • Flutter面试题、Dart面试题
  • SQL基础应用
  • javaEE-网络原理-1初识
  • Django 项目中的高效日志管理:从配置到实践
  • Windows平台ROBOT安装
  • Socket套接字
  • Celeborn和HDFS、YARN混合部署
  • 算法 Class 006(二分搜索)
  • SQL 基础教程 - SQL ORDER BY 关键字
  • 华为的数字化转型框架和数字化转型成熟度评估方法
  • 在C语言中使用伪终端与bash交互