三分钟带您搞懂代理模式

简介: 三分钟带您搞懂代理模式


全文共1439字,预计阅读时间:10分钟

定义:

  代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。

  代理模式是一种比较贴近于生活的 设计模式,现实生活中也有很多代理模式的例子:

  1. 住酒店不一定需要亲自到酒店去,还可以通过微信支付下的同程艺龙来订酒店。
  2. 我们可以通过中介去找房子,不用直接跟房东沟通(现实生活中,我们更希望直接跟房东沟通)
  3. 春运买票买不到,我们可以找黄牛替我们抢票
  4. 想访问国外的网站,可以使用代理服务器进行访问。

  代理模式通常解决的问题是,我们没有办法直接访问某一个对象,但是却想使用这个对象的一些功能,这个时候我们就可以创建一个代理对象,通过访问代理对象,间接的访问这个对象。

  我们想去旅行,但是没有办法提前去目的地订酒店,所以我们通过同程艺龙来订酒店。同程艺龙就是一个代理对象,他和酒店一样,提供了订酒店的方法。

  我们没有渠道去直接联系房东,所以我们可以通过中介公司租房,房东把租房这件事委托给了中介公司,这里中介公司就是一个代理对象。代理对象除了调用真实对象的方法,还可以对方法进行增强。比如中介公司可以赚差价。

图解:

  这里可以看出,无论是代理对象和被代理对象,都实现了Subject接口,同时被代理对象作为代理对象的成员变量。这个结构与装饰模式非常像,下图是装饰模式的示意图:

那么它们之间有什么区别呢?

  首先从定义上可以看出,装饰模式强调的是添加职责,而代理模式强调的是间接访问。

  其次从结构设计上来说,装饰模式是将一个个功能进行拆分,使用时再动态的进行组装,生成不同功能的对象。而代理模式却是在编译之前就已经确定了代理对象和被代理对象之间的关系。

  最后就使用上来说,装饰模式需要客户端去组装对象,而代理模式却只需要客户端去调用代理对象,代理对象和被代理对象的关系被封装到了代理对象中,对用户而言是无感的。

实例:

  这里举一个订酒店的实例,小赵在同程艺龙上预定了橘子酒店,这里酒店就是图中的Subject,它提供了订酒店、付款的方法,橘子酒店就是RealSubject,它是酒店的一个具体实现。而同程艺龙作为酒店的代理,提供优质的客户服务,其中包括订酒店前的电话确认、订酒店后的客户回访、付款时提供红包减免等。

代码:

/**
 * 酒店.
 *
 * @author jialin.li
 * @date 2019-12-27 11:37
*/
public interface Hotel {
    /** 订酒店 **/
    void hotelBooking(String name);
    /** 付款 **/
    double pay();
}
/**
 * 橘子酒店.
 *
 * @author jialin.li
 * @date 2019-12-27 13:17
*/
public class OrangeHotel implements Hotel {
    @Override
    public void hotelBooking(String name) {
        System.out.println(name + ",欢迎入住橘子酒店");
    }
    @Override
    public double pay() {
        return 120d;
    }
}
/**
 * 同程艺龙
 *
 * @author jialin.li
 * @date 2019-12-27 13:20
*/
public class Elong implements Hotel{
    private Hotel hotel;
    public Elong() {
        hotel = new OrangeHotel();
    }
    @Override
    public void hotelBooking(String name) {
        System.out.println(confirm(name));
        hotel.hotelBooking(name);
        System.out.println(callback(name));
    }
    @Override
    public double pay() {
        return useHongbao(hotel.pay());
    }
    private String confirm(String name){
        return "亲爱的"+name+"您预定了橘子酒店,记得入住哦!";
    }
    private String callback(String name){
        return "亲爱的"+name+"您的入住已经结束,有问题请及时反馈!";
    }
    private double useHongbao(double price){
        return price - 50.0d;
    }
}
/**
 * 测试类.
 *
 * @author jialin.li
 * @date 2019-12-27 13:36
*/
public class Main {
    public static void main(String[] args) {
        String xiaozhao = "小赵";
        Elong elong = new Elong();
        elong.hotelBooking(xiaozhao);
        System.out.print("共花费了:");
        System.out.println(elong.pay());
    }
}

结果:

亲爱的小赵您预定了橘子酒店,记得入住哦!

小赵,欢迎入住橘子酒店

亲爱的小赵您的入住已经结束,有问题请及时反馈!

共花费了:70.0

有没有什么问题?

  可以看出,我们在代理类中直接引用了被代理对象,所以代理类和被代理类是一种一对一的关系,即我们需要为每一个被代理类,创建一个代理类。

  假设我们现在有一个打点的需求,要为系统中的一批对象增加记录日志的方法,如果使用代理模式,就要为这一批对象创建代理类,这样的工作量是无疑是巨大的。那么有没有什么办法可以让我们可以少写或者不写代理类,却能完成代理功能呢?这就要引出了我们要讲的一个概念——动态代理(动态代理涉及到、反射类加载的一些知识,所以在下一篇文章中讲解)

相关文章
|
9月前
|
设计模式 Java 程序员
谈谈代码:漫谈代理模式
代理模式是在编程中非常常见的设计模式.笔者在面试的过程中也经常会问到相关的问题,但是很多同学答的并不尽人意
74 0
谈谈代码:漫谈代理模式
|
9月前
|
设计模式 XML JSON
二十三种设计模式全面解析-代理模式进阶篇:揭秘远程代理
二十三种设计模式全面解析-代理模式进阶篇:揭秘远程代理
175 0
|
3天前
|
设计模式 缓存 Java
「全网最细 + 实战源码案例」设计模式——代理模式
代理模式(Proxy Pattern)是一种结构型设计模式,通过代理对象控制对目标对象的访问并添加额外功能。它分为静态代理和动态代理,后者包括JDK动态代理和CGLIB动态代理。JDK动态代理基于接口反射生成代理类,而CGLIB通过继承目标类生成子类。代理模式适用于延迟初始化、访问控制、远程服务、日志记录和缓存等场景,优点是职责分离、符合开闭原则和提高安全性,缺点是增加系统复杂性。
54 25
|
1天前
|
设计模式 前端开发 数据库
「全网最细 + 实战源码案例」设计模式——桥接模式
桥接模式(Bridge Pattern)是一种结构型设计模式,通过将抽象部分与实现部分分离,使它们可以独立变化,从而降低代码耦合度,避免类爆炸,提高可扩展性。其结构包括实现类接口、具体实现类、抽象类和精确抽象类。适用于多维度扩展类、隐藏实现细节、简化庞杂类以及运行时切换实现方法的场景。优点包括高扩展性、隐藏实现细节、遵循开闭原则和单一职责原则;缺点是可能增加代码复杂度。示例中展示了不同操作系统播放不同格式视频文件的实现。
30 15
|
6月前
|
Java 程序员 容器
十分钟搞懂依赖注入
依赖注入(DI)是软件开发中的关键技术,它将类的依赖关系转移至外部管理,提升了代码的模块化和可测试性。如同炒菜时调料不由厨师直接添加,而是由调料师准备并递送,程序员只需声明所需依赖,外部机制如DI容器会负责实例化并注入这些依赖。这样,类变得更灵活且易于测试,同时也促进了代码的模块化。例如,在Java中,可以通过构造函数注入Logger接口的不同实现(如ConsoleLogger和FileLogger),使Application类与其具体实现解耦。
|
6月前
|
设计模式
设计模式的基础问题之代理模式在工作中的问题如何解决
设计模式的基础问题之代理模式在工作中的问题如何解决
|
9月前
|
设计模式 Java
Java设计模式【十三】:代理模式
Java设计模式【十三】:代理模式
37 0
|
设计模式 缓存 安全
2023-6-29-第十一式代理模式
2023-6-29-第十一式代理模式
78 0
|
设计模式 监控 Java
代理模式看这一篇就够了~
代理模式看这一篇就够了~
692 1
|
Java 数据库连接 数据库
信不信十分钟让你彻底搞懂java反射
概念:反射是Java的一种机制,让我们可以在运行时获取类的信息 作用:通过反射,我们可以在程序运行时动态创建对象,还能获取到类的所有信息,比如它的属性、构造器、方法、注解等;
18185 2
信不信十分钟让你彻底搞懂java反射