设计模式—结构型模式之代理模式

news2024/12/24 0:49:55

设计模式—结构型模式之代理模式

代理模式(Proxy Pattern) ,给某一个对象提供一个代理,并由代理对象控制对原对象的引用,对象结构型模式。

静态代理

比如我们有一个直播平台,提供了直播功能,但是如果不进行美颜,可能就比较冷清。所以美颜功能就是我们的增强,可以用静态代理来实现。

直播接口:

/**
 * 直播接口
 */
public interface LiveBroadCastInterface {
    void liveBroadcast();
}

直播类:

/**
 * 实现直播接口
 */
public class SjdwzLiveBroadCast implements LiveBroadCastInterface{
    @Override
    public void liveBroadcast() {
        System.out.println("我来直播了......");
    }
}

如果没有美颜,可能就会比较冷清;所以我们可以提供一个静态代理,来为我们的直播进行增强。

要代理的功能类要和原类型实现相同的接口。

public class SjdwzStaticProxy implements  LiveBroadCastInterface{
    
    private LiveBroadCastInterface liveBroadCastInterface;

    public SjdwzStaticProxy(LiveBroadCastInterface liveBroadCastInterface) {
        this.liveBroadCastInterface = liveBroadCastInterface;
    }

    @Override
    public void liveBroadcast() {
        System.out.println("这是代理的功能");
        System.out.println("美颜--------");
        System.out.println("=========原功能如下=========");
        this.liveBroadCastInterface.liveBroadcast();
    }
}

测试类如下:

public class StaticSjdwzProxyTest {
    public static void main(String[] args) {
        SjdwzStaticProxy sjdwzStaticProxy = new SjdwzStaticProxy(new SjdwzLiveBroadCast());
        sjdwzStaticProxy.liveBroadcast();
    }
}

运行如下:

运行截图

jdk动态代理

还是上面的例子,可以使用JDK的动态代理来实现:

/**
 * 实现InvocationHandler的作用是为了在本类实现增强方法,
 * @param <T> 要代理对象实现的接口
 */
public class JdkLiveBroadCastProxy<T> implements InvocationHandler {

    //被代理对象
    private T target;

    public JdkLiveBroadCastProxy(T target) {
        this.target = target;
    }

    public static<T> T getProxy(T t){
        /**
         * ClassLoader loader, 当前被代理对象的类加载器
         * Class<?>[] interfaces, 当前被代理对象所实现的所有接口
         * InvocationHandler h,
         *  当前被代理对象执行目标方法的时候我们使用h可以定义拦截增强方法
         */
        Object o = Proxy.newProxyInstance(
                t.getClass().getClassLoader(),
                t.getClass().getInterfaces(), //必须接口
                new JdkLiveBroadCastProxy(t));
        return (T)o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("这是代理的一些功能======");
        System.out.println("原本的功能===========");
        //反射执行
        Object invoke = method.invoke(this.target, args);
        System.out.println("返回值:"+invoke);
        return invoke;
    }
}

测试类如下:

public class JdkLiveBroadCastProxyTest {
    public static void main(String[] args) {
        LiveBroadCastInterface proxy = JdkLiveBroadCastProxy.getProxy(new SjdwzLiveBroadCast());
        proxy.liveBroadcast();
    }
}

运行结果如下:

运行截图

要求

JDK要求被代理对象必须有接口,因为必须有接口才能告诉代理有哪些方法。

cglib动态代理

我们发现,如果使用JDK的动态代理,必须实现接口。cglib动态代理是不需要实现接口的。

首先我们在项目的pom文件中引入依赖:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

cglib动态代理类如下:

public class CglibProxy {

    //为任意对象创建代理
    public static<T> T createProxy(T t){
        //1、创建一个增强器
        Enhancer enhancer = new Enhancer();

        //2、设置要增强哪个个类的功能。增强器为这个类动态创建一个子类
        enhancer.setSuperclass(t.getClass());

        //3、设置回调
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj,
                                    Method method,  //为了能获取到原方法的一些元数据信息
                                    Object[] args,
                                    MethodProxy proxy) throws Throwable {
                //编写增强的逻辑
                System.out.println("cglib的动态代理增强的功能===========");
                System.out.println("原功能===========");
                //目标方法进行执行
                Object invoke = proxy.invokeSuper(obj,args);
                return invoke;
            }
        });

        Object o = enhancer.create();
        return (T) o;
    }

}

测试类如下:

public class MyCglibProxyTest {
    public static void main(String[] args) {
        SjdwzLiveBroadCast proxy = CglibProxy.createProxy(new SjdwzLiveBroadCast());
        proxy.liveBroadcast();
    }
}

运行截图如下:

运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1204643.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

activiti7审批驳回,控制变量无法覆盖,导致无限循环驳回,流程无法结束

项目开发过程中使用工作流&#xff0c;因此考虑使用activiti7做完工作流引擎。项目开发过程中&#xff0c;发现流程驳回时&#xff0c;再次执行流程&#xff0c;控制变量无法覆盖&#xff0c;导致无限循环驳回&#xff0c;流程无法结束。流程图如下图所示&#xff1a; 驳回控制…

2023年数维杯国际大学生数学建模挑战赛

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 cs数模团队在数维杯前为大家提供了许多资料的内容呀&#xff0…

kubernetes--Pod进阶

目录 一、资源限制&#xff1a; 1. 资源限制的两种规范&#xff1a; 2. Pod 和 容器 的资源请求和限制&#xff1a; 3. CPU 资源单位&#xff1a; 4. 内存资源单位 &#xff1a; 5. 资源限制示例&#xff1a; 二、健康检查&#xff1a;探针&#xff08;Probe&#xff09; 1. 探…

深入理解强化学习——马尔可夫决策过程:马尔可夫过程和马尔科夫链

分类目录&#xff1a;《深入理解强化学习》总目录 马尔可夫过程是一组具有马尔可夫性质的随机变量序列 S 1 , S 2 , ⋯ , S t S_1, S_2, \cdots, S_t S1​,S2​,⋯,St​&#xff0c;其中下一个时刻的状态 S t 1 S_{t1} St1​只取决于当前状态 S t S_t St​ 。我们设状态的历史…

JVM:如果是你,你如何解决跨代引用的问题?(记忆集和卡集)

这部分内容主要是为了稍后介绍各款垃圾收集器时做前置知识铺垫&#xff0c;如果对这部分内容感到枯燥或者疑惑&#xff0c;可以先放下看&#xff0c;等后续遇到要使用它们的实际场景、实际问题时再结合问题&#xff0c;再回来阅读和理解。 记忆集和卡集 前面在分代收集理论那…

第十六章,反射与注解例题

package 例题; import java.lang.reflect.Constructor;class 例题1Demo {//变量String s;int i, i2, i3;private 例题1Demo() {//无参构造方法}protected 例题1Demo(String s, int i) {//有参构造方法this.s s;this.i i;}public 例题1Demo(String... strings) throws NumberF…

jupyter lab常用插件集合

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

032-从零搭建微服务-定时服务(一)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;mingyue: &#x1f389; 基于 Spring Boot、Spring Cloud & Alibaba 的分布式微服务架构基础服务中心 源…

【Git】第二篇:基本操作(创建本地仓库)

我们知道&#xff0c;git是一个版本控制器&#xff0c;可以帮我们控制管理电脑上所有格式的文档。 而我们需要使用git管理文件的时候&#xff0c;我们必须将这些文件放到git仓库中&#xff0c;只有在git仓库中的文件才可以被我们的git追踪管理 创建本地仓库 创建本地仓库是需…

【BMC】jsnbd介绍

jsnbd介绍 本文主要介绍一个名为jsnbd的开源项目&#xff0c;位于GitHub - openbmc/jsnbd&#xff0c;它实现了一个前端&#xff08;包含HTML和JS文件&#xff09;页面&#xff0c;作为存储服务器&#xff0c;可以指定存储内容&#xff1b;还包含一个后端的代理&#xff0c;这…

5. HTML常用标签

5.1 标签语义 学习标签是有技巧的&#xff0c;重点是记住每个标签的语义。简单理解就是指标签的含义。即这个标签是用来干嘛的。 根据标签的语义&#xff0c;在合适的地方给一个最为合理的标签。可以让页面结构给清晰。 5.2 标题标签 <h1>-<h6>(重要) HTML提供了…

【C++】类和对象(1)--初识

目录 一 类的引入 二 类的定义 1 类的两种定义方式: (1) 声明和定义全部放在类体中 (2) 类声明放在.h文件中&#xff0c;成员函数定义放在.cpp文件中 2 成员变量命名规则的建议 三 类的访问限定符及封装 1 访问限定符 2 封装 四 类的作用域 五 类的实例化 六 类对象…

图的表示与基础--Java

1.图的基础知识 该图片来自于&#xff1a; https://b23.tv/KHCF2m6 2.稀疏图与稠密图 G(V,E)&#xff1a;V顶点个数&#xff0c;E边的个数 稀疏图&#xff1a;E<<V 一般用邻接表表示(数组链表) 稠密图&#xff1a;E接近V 一般用邻接矩阵表示&#xf…

Java-多线程基础篇

前言&#xff1a; 以下是看马老师的视频以及自己阅读《Java多线程编程实战指南》所总结的基础内容&#xff0c;只是个人理解&#xff0c;如有不对还请大家指正。 1.线程的概念&#xff1a; 来自于百度百科&#xff1a;线程是独立调度和分派的基本单位。在Unix System V及Sun…

测试行业爬了7年,从功能测试到高级测试,工资也翻了好几倍

我在测试行业爬了7年。从功能测试到现在成为高级测试&#xff0c;我的工资也翻了好几倍。 入门阶段&#xff08;功能测试&#xff09; 个人认为&#xff0c;测试的前景还不错&#xff0c;只要你肯努力&#xff1b;刚出来的时候在鹅厂做外包功能测试。每天都很悠闲。点了两年&a…

Java16新增特性

前言 前面的文章&#xff0c;我们对Java9、Java10、Java11、Java12 、Java13、Java14、Java15 的特性进行了介绍&#xff0c;对应的文章如下 Java9新增特性 Java10新增特性 Java11新增特性 Java12新增特性 Java13新增特性 Java14新增特性 Java15新增特性 今天我们来一起看一下…

【深圳1024开发者城市聚会】主理人视角的聚会现场,一起来看看有啥不一样的东西

【深圳1024开发者城市聚会】主理人视角的聚会现场&#xff0c;一起来看看有啥不一样的东西 今年的1024&#xff0c;我们在深圳&#xff0c;玩点不一样的… 文章目录 1 活动背景2 活动宣传3 活动准备4 活动现场布置会场会场引导签到深圳站视频展播前半程议题分分享简单茶歇后半场…

轻量封装WebGPU渲染系统示例<28>- MRT纹理(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/MRT.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: export class MRT {private mRscene new RendererScene();initial…

错误:FUNCTION simple_notebook.count does not exist.解决方法

0 引入问题 小王&#xff1a;你这个数据有问题啊&#xff0c;有时候还会报错 小腾&#xff1a;怎么会有问题呢&#xff0c;代码写的一点毛病也没有 小王&#xff1a;没问题怎么会报错&#xff0c;你赶紧看看&#xff0c;项目上线甲方看到了报给老板咱俩就寄了 小腾&#xff1a…