4.16--设计模式之创建型之代理模式(总复习版本)---脚踏实地,一步一个脚印

news/2024/7/6 6:30:02 标签: 代理模式, 设计模式, java

1.代理对象
定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用,从而实现对真实对象的操作。
通俗的来讲代理模式就是我们生活中常见的中介

代理模式中,代理对象主要起到一个中介的作用,用于协调与连接调用者(即客户端)和被调用者(即目标对象),在一定程度上降低了系统的耦合度,同时也保护了目标对象。 缺点是在调用者与被调用者之间增加了代理对象,可能会造成请求的处理速度变慢。

2.代理模式分为三类:

  1. 静态代理
  2. 动态代理
  3. CGLIB代理

结构图:

在这里插入图片描述

1.Subject:抽象角色,声明了真实对象和代理对象的共同接口;
2.Proxy:代理角色,实现了与真实对象相同的接口,所以在任何时刻都能够代理真实对象,并且代理对象内部包含了真实对象的引用,所以它可以操作真实对象,同时也可以附加其他的操作,相当于对真实对象进行封装。
3.RealSubject:真实对象,是我们最终要引用的对象

静态代理
静态代理模式由三个部分构成:

1.一个公共的接口
2.一个被代理角色
3.一个代理角色

1.创建公共的接口


//公共接口
public interface Rent {
    void renting();
}

2.创建被代理角色


//被代理对象
public class Corey implements Rent{
    //这是被代理对象!(房主)
    @Override
    public void renting() {
        System.out.println("Corey有房出租");
    }
}

3.创建代理角色

//代理对象(中介)
public class StaticProxyRent implements Rent{
    private Rent rent;

    public StaticProxyRent(Rent rent){
        this.rent = rent;
    }

    @Override
    public void renting() {
        System.out.println("向房客出租房屋");
        this.rent.renting();
        System.out.println("完成售后服务");
    }
}


  1. 创建测试类
public class StaticProxyTest {
    public static void main(String[] args) {
        Rent rent = new Corey();
        StaticProxyRent staticProxyRent = new StaticProxyRent(rent);
        staticProxyRent.renting();
    }
}


  1. 使用 JDK 的 Proxy 类实现动态代理
    1、 创建业务接口
public interface JdkProxyRent {
    void renting();
}

2、 创建接口实现类

public class JdkProxyCorey implements JdkProxyRent {
    @Override
    public void renting() {
        System.out.println("Corey 有房出租!");
    }
}
  1. 创建生成代理对象的工厂
//动态生成代理对象的工厂
public class JdkProxyFactory {

    //动态生成代理对象
    public static Object getProxyBean(Object target){
        Class clazz = target.getClass();
        MyAspect myAspect = new MyAspect();
        //在JDK中动态生成代理对象的方法
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
            //动态生成代理对象的方法
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                myAspect.before();
                Object obj =  method.invoke(target,args);
                myAspect.after();
                return obj;
            }
        });
    }
}


4.创建切面对象


public class MyAspect {
    public void before(){
        System.out.println("带领房客看房...签租房协议");
    }
    public void after(){
        System.out.println("售后服务");
    }
}


5.创建测试类

public class jdkProxyTest {
    public static void main(String[] args) {
        JdkProxyRent jdkProxyRent = new JdkProxyCorey();
        JdkProxyRent jdkProxyRent1 =(JdkProxyRent)JdkProxyFactory.getProxyBean(jdkProxyRent);
        jdkProxyRent1.renting();

    }
}


3.使用 CGLIB 实现动态代理
CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它被许多框架所使用,其底层是通过使用一个小而快的字节码处理框架 ASM(Java 字节码操控框架)转换字节码并生成新的类。因此 CGLIB 要依赖于 ASM 的包。
JDK 的动态代理机制只能代理实现了接口的类,而对于没有实现接口的类就不能使用JDK 的 Proxy 类生成代理对象,cglib 是针对类来实现代理的,他的原理是对指定的目标类生成一个子类并通过回调的方式来实现增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。

1.添加 jar 包
cglib.jar
asm.jar

2.创建业务接口

public interface CglibProxyRent {
    void renting();
}

3.创建接口实现类


public class CglibProxyCorey implements CglibProxyRent {
    @Override
    public void renting() {
        System.out.println("Corey 有房出租");
    }
}

4.创建生成代理对象的工厂

public class CglibProxyBeanFactory {
    public static Object getProxyBean(CglibProxyRent rent){
        CglibMyAspect myAspect = new CglibMyAspect();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(rent.getClass());
        enhancer.setCallback(new MethodInterceptor() {

            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                myAspect.before();
                Object obj = method.invoke(rent,objects);
                myAspect.after();
                return obj;
            }
        });
        return enhancer.create();
    }
}

  1. 创建切面
public class CglibMyAspect {
    public void before(){
        System.out.println("带领客户看房,签订租房协议");
    }

    public void after(){
        System.out.println("售后服务");
    }
}
  1. 创建测试类
public class Test {
    public static void main(String[] args) {
        CglibProxyRent rent = new CglibProxyCorey();
        CglibProxyRent rent1 = (CglibProxyRent) CglibProxyBeanFactory.getProxyBean(rent);
        rent1.renting();
    }
}



http://www.niftyadmin.cn/n/228106.html

相关文章

HR:这些IntelliJ IDEA的面试题,请好好看看

文章目录摘要IntelliJ IDEA 中如何使用代码自动生成工具?IntelliJ IDEA 如何优化代码?IntelliJ IDEA 中如何调试 Java 应用程序?IntelliJ IDEA 中如何使用 Maven构建项目?摘要 本文将介绍一些常见的IntelliJ IDEA面试题。文章将涵…

java继承类怎么写

继承类是通过把父类的方法和属性继承到一个类中,而子类的方法和属性是子类自己定义的。 Java中有一个很重要的概念叫做继承,这也是 Java语言的精髓所在。Java语言提供了一种机制,叫做派生类。在 Java中,如果没有实现了某个派生类方…

记录踩过的坑-sklearn

目录 安装 使用逻辑回归报错:STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. 内置的MNIST数据集 sklearn中的svm sklearn中的svm训练太慢 安装 pip install scikit-learn 使用逻辑回归报错:STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. 增加迭代…

vmware 打开报错

Error: VMware Workstation failed? I downloaded ccleaner to free up my ram and to get rid of some junk files. I ran ccleaner, tried to start my vmware and I got the error message “VMware Workstation failed to start the VMware Authorization Service. You ca…

如何开启tiktok之旅

关于tiktok的用户规模,相比国内抖音而言的机会这里就不再多说了,我之所以研究tiktok,是因为有不少客户咨询了我们tiktok加速方案,我们自身是一家纯网络公司,只提供tiktok加速方案而已,但是遭不住需求量大。…

面试题30天打卡-day05

1、Java 中 hashCode 和 equals 方法是什么?它们和 各有什么区别? 在 Java 中,hashCode 和 equals 方法都是 Object 类的方法。它们的作用分别如下: hashCode 方法返回对象的哈希码,用于支持基于哈希表的集合&#…

《AI在音乐创作中的应用》

目录 一 引言 二 音乐生成的基本概念 2.1 音乐表示 2.2 音乐理论基础

波形失真总结

失真是输入信号与输出信号在幅度比例关系、相位关系及波形形状产生变化的现象。音频功放的失真分为电失真和声失真两大类。电失真是由电路引起的,声失真是由还音器件扬声器引起的。电失真的类型有:谐波失真、互调失真、瞬态失真。声失真主要是交流接口失…