Java设计模式之代理模式

概念和作用

代理模式是一种结构型设计模式,它允许为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以在目标对象执行某些操作前后添加额外的功能。

使用场景

**1.访问控制:**根据用户权限决定是否允许访问目标对象。

**2.日志记录:**在访问目标对象前后记录日志信息。

**3.性能监控:**测量目标对象方法的执行时间。

**4.延迟加载:**按需加载资源,避免过早占用内存。

举例

静态代理

静态代理在编译时就确定了代理类和目标类的关系。

复制代码
// 目标接口
public interface ITeacher {
    void teach();
}

// 目标类
public class Teacher implements ITeacher {
    @Override
    public void teach() {
        System.out.println("老师正在授课");
    }
}

// 代理类
public class TeacherProxy implements ITeacher {
    private Teacher teacher;

    public TeacherProxy(Teacher teacher) {
        this.teacher = teacher;
    }

    @Override
    public void teach() {
        // 前置操作
        System.out.println("开始上课前的准备工作");
        teacher.teach();
        // 后置操作
        System.out.println("课程结束,安排课后作业");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        TeacherProxy proxy = new TeacherProxy(teacher);
        proxy.teach();
    }
}

动态代理

动态代理在运行时动态生成代理类,更加灵活。

复制代码
// 目标接口
public interface ITeacher {
    void teach();
}

// 目标类
public class Teacher implements ITeacher {
    @Override
    public void teach() {
        System.out.println("老师正在授课");
    }
}

// 动态代理类
public class DynamicProxy implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置操作
        System.out.println("开始上课前的准备工作");
        Object result = method.invoke(target, args);
        // 后置操作
        System.out.println("课程结束,安排课后作业");
        return result;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        DynamicProxy proxy = new DynamicProxy(teacher);
        ITeacher iTeacher = (ITeacher) proxy.getProxyInstance();
        iTeacher.teach();
    }
}

优点和缺点

优点

**1.职责分离:**将核心业务逻辑与附加功能分离,符合单一职责原则。

**2.增强功能:**可以在不修改目标对象代码的情况下增强其功能。

**3.灵活扩展:**动态代理可以在运行时为不同目标对象生成代理,具有很高的灵活性。

缺点

**1.性能开销:**代理模式会增加一定的性能开销,尤其是动态代理。

**2.代码复杂度增加:**需要额外编写代理类代码,增加了系统的复杂度。

不使用代理模式

如果不使用代理模式,我们可能需要直接在目标对象的方法中添加额外的功能,或者通过继承目标类并重写方法来实现。例如:

复制代码
public class EnhancedTeacher extends Teacher {
    @Override
    public void teach() {
        // 前置操作
        System.out.println("开始上课前的准备工作");
        super.teach();
        // 后置操作
        System.out.println("课程结束,安排课后作业");
    }
}

这种方式虽然简单,但存在以下问题:

**1.侵入性修改:**需要修改目标类的代码或继承目标类,违反了开闭原则。

**2.复用性差:**如果多个目标类需要相同的附加功能,需要重复编写代码。

**3.耦合度高:**客户端直接依赖具体的增强类,不利于系统的扩展和维护。

综上所述,代理模式是一种非常实用的设计模式,在需要增强对象功能、控制对象访问等场景下具有广泛的应用价值。

相关推荐
夕除1 小时前
redis--主从还是集群,内存
java·spring·mybatis
百数平台1 小时前
低代码安全技术实践:表单 / 流程 / 报表三级权限体系设计解析
java·大数据·数据库
白露与泡影1 小时前
Spring Boot 实现验证码:Hutool-captcha、AJ-Captcha、EasyCaptcha 到底怎么选?
java·spring boot·后端
马优晨1 小时前
Java中的dto是什么
java·开发语言·java中的dto是什么·java的dto是什么·dto在java中是什么
小蒜学长1 小时前
基于Springboot+Vue的高校教师教学业绩综合管理系统的设计与开发(代码+数据库+LW)
java·数据库·spring boot·后端·教学业绩管理·三级权限
Mikko71 小时前
Spring Boot 3.5.16 自带的 Tomcat 10.1.55 中了哪些 CVE?其中一条是修上一个漏洞时带进来的
java·spring boot·后端·安全·tomcat
十年Java程序媛1 小时前
Java 内部类全解|成员 / 静态 / 匿名内部类,理清和 Lambda 的区别
java·spring boot·面试
SL_staff2 小时前
报工≠打卡:从任务报工到闭环管控的5个数据断点排查清单
java·spring boot·全栈
tryxr2 小时前
如何优化sql
java·数据库·sql·数据库优化
SamDeepThinking2 小时前
配货单发货数为空告警误报治理:写表延迟复核方案
java·后端·架构