设计模式之代理模式

本文深入讲解Java中的代理模式,包括其定义、作用及静态代理与动态代理的区别。通过实例演示了如何使用代理模式来增强真实角色的功能,同时保持代码的清晰和可扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

想学习好java,我想是绕不过去设计模式这个坎的,所以今天就代理模式以及动态代理和静态代理给大家讲解一下。这篇文章我们从什么是代理模式,代理模式的作用,有哪几种代理模式来展开讲解!

正文:

一、什么是代理模式

代理模式:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式的组成:

抽象角色通过接口或抽象类声明真实角色实现的业务方法
代理角色实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用

代理模式的结构图 :

 

抽象角色类,定义了真实角色代理角色的共用接口,这样就在任何使用真实角色的地方都可以使用代理角色

举个例子说明,假如说现在我想吃饭,但是吃饭的地方要走一段距离,我又懒得动了,这时候我就可以通过外卖平台来点餐,他们帮我把附近的饭陈列出来,然后并把我想吃的饭送到家。我只需要选择我喜欢吃的饭,然后付钱就可以啦。

1.创建抽象角色接口

public interface BuyFood {
   void buyFood();
}

2.创建真实角色

public class BuyFoodImpl implements BuyFood {
    @Override
    public void buyFood() {
        System.out.println("我要买土豆回锅肉盖饭");
    }
}

3.创建代理角色

public class BuyFoodProxy implements BuyFood {
    private BuyFoodImpl buyFood;

    public BuyFoodProxy() {
        buyFood=new BuyFoodImpl();
    }

    @Override
    public void buyFood() {
        System.out.println("去饭店取土豆回锅肉盖饭");
        buyFood.buyFood();
        System.out.println("请好好用餐");
    }
}

4.客户端代码

public class Client {
    public static void main(String[] args) {
        BuyFoodProxy buyFoodProxy = new BuyFoodProxy();
        buyFoodProxy.buyFood();
    }
}

执行结果: 

去饭店取土豆回锅肉盖饭
我要买土豆回锅肉盖饭
请好好用餐

这样外卖平台就帮我买到饭啦,我也不用亲自下楼买饭啦。

二、代理模式的作用

1.职责清晰

真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。

2.代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。

3.高扩展性 

4.开闭原则,增加功能  

我们可以通过代理角色的代码里加功能来扩展真实角色的功能,这样我们只需要修改代理角色而不需要在修改委托角色,符合代码设计的开闭原则。

三、代理的分类

根据以上对代理的理解,对于代理的具体实现,我们有不同的方式,如果按照代理的创建时期,代理类可以分为两种:静态代理和动态代理。

静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

动态代理:在程序运行时,运用反射机制动态创建的。

上面的第一个例子就是静态代理。

那么换成动态代理的写法:

1.编写动态处理器

public class DynamicProxyHandler implements InvocationHandler{

    private Object object;
    
    public DynamicProxyHandler (Object object){
        this.object=object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("去饭店取土豆回锅肉盖饭");
        Object invoke = method.invoke(object, args); 
        System.out.println("请好好用餐");
        return invoke;
    }
}

2.客户端代码

public class DynamicProxyClient {
    public static void main(String[] args) { 
       BuyFoodImpl buyFood = new BuyFoodImpl();
       BuyFood proxyBuyFood = (BuyFood)Proxy.newProxyInstance(BuyFood.class.getClassLoader(), new Class[]{BuyFood.class}, new DynamicProxyHandler(buyFood));
       proxyBuyFood.buyFood();
    }
}

 注意Proxy.newProxyInstance()方法接受三个参数:

ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的

Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型

InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法

总结:

今天代理模式就讲到这里,还有很多设计模式需要我们去理解,我们一定要反复去理解,反复去看,并尽量思考是否可以把这些设计模式应用到实际开发中。一开始不明白也无所谓,反复去和同事讲和基友讲,讲的多了,也许你发现哪天醒来就理解啦。

我是阿达,一名喜欢分享知识的程序员,时不时的也会荒腔走板的聊一聊电影、电视剧、音乐、漫画,这里已经有350位小伙伴在等你们啦,感兴趣的就赶紧来点击关注我把,哪里有不明白或有不同观点的地方欢迎留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心的码字达

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值