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

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

一、核心思想

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

二、定义与结构

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

结构

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

角色

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

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

三、实现步骤及代码示例

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

静态代理

  1. 定义抽象主题接口:
java 复制代码
public interface Subject {
    void request();
}
  1. 实现真实主题类:
java 复制代码
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}
  1. 实现代理主题类:
java 复制代码
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. 客户端代码:
java 复制代码
public class Client {
    public static void main(String[] args) {
        Subject subject = new ProxySubject();
        subject.request();
    }
}

动态代理

  1. 定义抽象主题接口(同上)。
  2. 实现真实主题类(同上)。
  3. 创建InvocationHandler实现类:
java 复制代码
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. 客户端代码:
java 复制代码
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、网络请求代理服务器

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

  • 定义抽象主题(网络请求接口):
java 复制代码
interface NetworkRequest {
    String request(String url);
}
  • 真实主题(实际的网络请求实现):
java 复制代码
class RealNetworkRequest implements NetworkRequest {
    @Override
    public String request(String url) {
        System.out.println("Sending request to " + url);
        // 这里可以是实际的网络请求代码,比如使用HttpURLConnection等
        return "Response from " + url;
    }
}
  • 代理(带有缓存功能的网络请求代理):
java 复制代码
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;
        }
    }
}
  • 使用示例:
java 复制代码
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(面向切面编程)示例:

java 复制代码
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. 请求处理变慢:在客户端和目标对象之间增加一个代理对象,可能会造成请求处理速度变慢。

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

相关推荐
ByteBlossom6668 分钟前
Go语言的数据库交互
开发语言·后端·golang
Mr.Liu612 分钟前
小程序26-事件绑定和事件对象
前端·微信小程序·小程序
小众AI17 分钟前
garak - 开源的 LLMs 漏洞扫描工具
人工智能·开源·ai编程
续亮~29 分钟前
Kafka核心参数与使用02
java·分布式·后端·kafka
匹马夕阳34 分钟前
vue3中onUpdated钩子函数和nextTick的具体使用场景和区别
前端·javascript·vue.js
前端7737 分钟前
vue管理后台搭建
前端·javascript·vue.js
Power202466639 分钟前
NLP论文速读|基于主动检索的渐进多模态推理
人工智能·深度学习·机器学习·自然语言处理·nlp
续亮~42 分钟前
Spring Boot 项目中集成 Kafka-03
java·spring boot·后端·kafka
未来之窗软件服务1 小时前
软件架构设计——通用表单UI-提示确认框—未来之窗行业应用跨平台架构
前端·javascript·ui
csdn_aspnet1 小时前
在 ASP.NET CORE 中上传、下载文件
后端·asp.net·.netcore