设计模式 – 代理模式

news/2024/11/6 5:27:20

1 概述

在生活中,我们经常见到这样的场景,如:租房中介、售票黄牛、婚介、经纪人、快递、事务代理、非侵入式日志监听等,这些都是代理模式的实际体现。代理模式(Proxy
Pattern)的定义也非常简单,是指为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客服端和目标对象之间起到中介作用,代理模式属于结构型设计模式。使用
代理模式主要有两个目的:一保护目标对象,二增强目标对象。下面我们来看一下代理模式的类结构图:
在这里插入图片描述
Subject 是顶层接口,RealSubject 是真实对象(被代理对象),Proxy 是代理对象,代理对象持有被代理对象的引用,客户端调用代理对象方法,同时也调用被代理对象的方
法,但是在代理对象前后增加一些处理。在代码中,我们想到代理,就会理解为是代码增强,其实就是在原本逻辑前后增加一些逻辑,而调用者无感知。代理模式属于结构型
模式,有静态代理和动态代理。

2 静态代理

举个例子:人到了适婚年龄,父母总是迫不及待希望早点抱孙子。而现在社会的人在各种压力之下,都选择晚婚晚育。于是着急的父母就开始到处为自己的子女相亲,比子女
自己还着急。这个相亲的过程,就是一种我们人人都有份的代理。来看代码实现:

public interface Person {
    void findLove();
}

public class Son implements Person {
    @Override
    public void findLove() {
        System.out.println("儿子要求: 上海名媛");
    }
}

public class Father implements Person {
    private Son son;
    public Father(Son son) {
        this.son = son;
    }
    @Override
    public void findLove() {
        System.out.println("父母物色对象");
        son.findLove();
        System.out.println("双方同意交往,确立关系");
    }
}

public class Test {
    public static void main(String[] args) {
        Father father=new Father(new Son());
        father.findLove();
    }
}

在这里插入图片描述

3 动态代理

动态代理和静态对比基本思路是一致的,只不过动态代理功能更加强大,随着业务的扩展适应性更强。如果还以找对象为例,使用动态代理相当于是能够适应复杂的业务场景。不仅仅只是父亲给儿子找对象,如果找对象这项业务发展成了一个产业,进而出现了媒婆、婚介所等这样的形式。那么,此时用静态代理成本就更大了,需要一个更加通用的解决方案,要满足任何单身人士找对象的需求。我们升级一下代码,先来看 JDK 实现方式:

3.1 JDK 实现方式

使用JDK的java.lang.reflect.Proxy类的newProxyInstance方法实现动态代理:

public interface Person {
    void findLove();
}

public class Customer implements Person {
    @Override
    public void findLove() {
        System.out.println("上海名媛");
    }
}


public class JdkMeiPoInvocationHandler implements InvocationHandler {
    
    private Object target;

    public Object getInstance(Object target) {
        this.target = target;
        Class<?> clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object obj = method.invoke(target, args);
        after();
        return obj;
    }

    private void before(){
        System.out.println("我是媒婆:我要给你找对象,现在已经拿到你的需求");
    }

    private void after(){
        System.out.println("如果合适的话,就准备办事");
    }

}


public class JdkTest {

    public static void main(String[] args) {
        Person person= (Person) new JdkMeiPoInvocationHandler().getInstance(new Customer());
        person.findLove();

    }
}

在这里插入图片描述

3.2 cglib


<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.12</version>
</dependency>


public class CglibMeipo implements MethodInterceptor {


    public Object getInstance(Class<?> clazz)  {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }


    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws
            Throwable {
        before();
        Object obj = methodProxy.invokeSuper(o, objects);
        after();
        return obj;
    }


    private void before() {
        System.out.println("我是媒婆:我要给你找对象,现在已经拿到你的需求");
    }


    private void after() {
        System.out.println("如果合适的话,就准备办事");
    }
}

public class CglibCustomer {

    public void findLove(){
        System.out.println("上海名媛");
    }
}

public class CglibTest {

    public static void main(String[] args)  {

        CglibCustomer customer = (CglibCustomer) new CglibMeipo().getInstance(CglibCustomer.class);
        customer.findLove();

    }

}

在这里插入图片描述

4 静态代理和动态的区别

(1) 静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步新增,违背开闭原则。
(2) 动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则。
(3) 若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成,无需修改代理类的代码。

5 代理模式的优缺点

使用代理模式具有以下几个优点:
(1) 代理模式能将代理对象与真实被调用的目标对象分离。
(2) 一定程度上降低了系统的耦合度,扩展性好。
(3) 可以起到保护目标对象的作用。
(4) 可以对目标对象的功能增强

缺点:
(1) 代理模式会造成系统设计中类的数量增加。
(2) 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
(3) 增加了系统的复杂度。


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

相关文章

设计模式 – 委派模式

委派模式 委派模式不属于 GOF23 种设计模式中。委派模式&#xff08;Delegate Pattern&#xff09;的基本作用就是负责任务的调用和分配任务&#xff0c;跟代理模式很像&#xff0c;可以看做是一种特殊情况下的静态代理 的全权代理&#xff0c;但是代理模式注重过程&#xff0…

谁帮我弄个C++的小问题啊 高手来啊

"; cin>>more; } else { cout<<"/n/n请输入华氏度&#xff1a;"; cin<<user; cout<<"/n华氏度是&#xff1a;"<<user<<" /n华氏度是&#xff1a;"<<user/5*932; cout<<"想继续转换请…

设计模式 – 策略模式

策略模式 策略模式&#xff08;Strategy Pattern&#xff09;是指定义了算法家族、分别封装起来&#xff0c;让它们之间可以互 相替换&#xff0c;此模式让算法的变化不会影响到使用算法的用户。 使用场景 1、假如系统中有很多类&#xff0c;而他们的区别仅仅在于他们的行为…

文件默认权限umask掩码

umask命令 作用&#xff1a;用于显示、设置文件的缺省权限 格式&#xff1a;umask [-S]  -S表示以rwx形式显示新建文件缺省权限 系统的默认掩码是0022 文件创建时的默认权限 0666 - umask 目录创建时的默认权限 0777 - umask 所以创建文件的权限是 0666 - 0022 0644   …

谢谢啦~ 哪个高手帮我用C++解决个小问题啊

0)/*利用辗除法 y)<<endl;} y)<<endl; cout<<"他们的最小公倍数为: "<<Gbs(x y; cout<<"输入要求的两个数&#xff1a;"&#xff1b; cin>>x>>; cout<<"他们的最大公约数为: "<<Gcd(x b)…

设计模式实战,工厂+策略+单例 解决 if else 过多问题

场景 在支付选择中&#xff0c;可以选择京东白条、支付宝、微信、银联支付等。 public void payment(String payType) {if (payType.equals("JD")) {//京东支付} else if (payType.equals("Alibaba")) {//支付宝支付} else if (payType.equals("Tece…

学好C语言要注意哪些啊

C语言学得很浅 如果你是计算机专业的C语言学习 高校中的C语言开课初衷也是为了让学生更快的熟悉计算机软件中最底层的思想 个人感觉大学中的C语言 文件操作当年就被我老师忽略掉 学完指针和结构体之后应该就不会再讲了 我建议你首先学习C语言的编程思想 如果你所在为一所普通高…

设计模式 – 模板设计模式

模板设计模式 模板方法模式&#xff08;Template Method Pattern&#xff09;&#xff0c;又叫模板模式(Template Pattern)&#xff0c;在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现&#xff0c;但调用将以抽象类中定义的方式进行。 该模式的主…