代理模式-结构型

代理模式的定义与特点

代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

代理模式的主要优点有:

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
  • 代理对象可以扩展目标对象的功能;
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性

其主要缺点是:

  • 代理模式会造成系统设计中类的数量增加
  • 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
  • 增加了系统的复杂度;

那么如何解决以上提到的缺点呢?答案是可以使用动态代理方式

代理模式的结构与实现

代理模式的结构比较简单,主要是通过定义一个继承抽象主题的代理来包含真实主题,从而实现对真实主题的访问,下面来分析其基本结构和实现方法。

1. 模式的结构

代理模式的主要角色如下。

  1. 抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  2. 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  3. 代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

其结构图如图 1 所示。

在代码中,一般代理会被理解为代码增强,实际上就是在原代码逻辑前后增加一些代码逻辑,而使调用者无感知。

根据代理的创建时期,代理模式分为静态代理和动态代理。

  • 静态:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
  • 动态:在程序运行时,运用反射机制动态创建而成

2. 模式的实现

代理模式的实现代码如下:

//自己写的动态代理

package com.proxy;

import com.sun.deploy.net.proxy.ProxyHandler;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author Allen
 * @version 1.0
 * @date 2021/8/3 17:01
 * @功能说明
 */
//接口 代理前
public interface NewStar {
    public void sing();
    public void rap();
}
//无名小卒 代理实现类普通
class WuYiFan implements NewStar{
    public void sing() {
        System.out.println("我会唱歌");
    }
    public void rap() {
        System.out.println("我会Rap");
    }
}
//代理人
class DaiLi implements InvocationHandler {
    NewStar newStar;

    public DaiLi(NewStar newStar) {
        this.newStar = newStar;
    }
    public NewStar getDaiLiNewStar(){
        return (NewStar) Proxy.newProxyInstance(newStar.getClass().getClassLoader(),newStar.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //走普通类方法
        Object invoke = method.invoke(newStar,args);
        System.out.println("经过代理人的包装-------");
        return invoke;
    }

    public static void main(String[] args) {
        //普通人
        NewStar wuYiFan = new WuYiFan();
        //代理人
        DaiLi daiLi = new DaiLi(wuYiFan);
        //经过代理后的包装对象
        NewStar daiLiNewStar = daiLi.getDaiLiNewStar();
        daiLiNewStar.rap();
    }
}
posted @   8023渡劫  阅读(25)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示