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

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

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

静态代理

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

直播接口:

java 复制代码
/**
 * 直播接口
 */
public interface LiveBroadCastInterface {
    void liveBroadcast();
}

直播类:

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

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

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

java 复制代码
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();
    }
}

测试类如下:

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

运行如下:

jdk动态代理

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

java 复制代码
/**
 * 实现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;
    }
}

测试类如下:

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

运行结果如下:

要求

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

cglib动态代理

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

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

xml 复制代码
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

cglib动态代理类如下:

java 复制代码
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;
    }

}

测试类如下:

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

运行截图如下:

相关推荐
郝学胜-神的一滴17 小时前
Linux线程编程:从原理到实践
linux·服务器·开发语言·c++·程序人生·设计模式·软件工程
我爱学习_zwj17 小时前
前端设计模式:轻量级实战指南
设计模式·前端框架·状态模式
还是大剑师兰特17 小时前
前端设计模式:详解、应用场景与核心对比
前端·设计模式·大剑师
平凡之路无尽路2 天前
智能体设计模式:构建智能系统的实践指南
人工智能·设计模式·自然语言处理·nlp·aigc·vllm
冷崖2 天前
工厂模式-创建型
c++·设计模式
何中应2 天前
【面试题-5】设计模式
java·开发语言·后端·设计模式·面试题
沐森3 天前
在实战中运用泛型和动态trait(特质)
设计模式
lomocode3 天前
改一个需求动 23 处代码?你可能踩进了这个坑
后端·设计模式
喷火龙8号3 天前
JWT 认证方案深度对比:单 Token 扩展刷新 vs 双 Token 验证
后端·设计模式·架构
fakerth3 天前
【OpenHarmony】设计模式模块详解
c++·单例模式·设计模式·openharmony