代理模式(静态代理)

定义

代理模式为一个对象提供一个替身或占位符以控制对这个对象的访问。访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

使用代理模式创建代理对象,让代理对象(representative)控制对某对象的访问,被代理的对象可以是远程对象、创建开销大的对象或者是需要安全控制的对象。

代理模式属于对象结构型模式。

代理分为静态代理和动态代理两种。


要点

优点:

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
  • 代理对象可以扩展目标对象的功能;
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;

缺点:

  • 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
  • 增加了系统的复杂度;

模式的结构:
代理模式的主要角色:
抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
在这里插入图片描述

场景

小张有一套房子想出租,但是由于工作原因没时间和租户沟通联系,于是小张将自己的房子交给中介帮忙出租,租户不会与房主小张接触,与小张接触的是中介,租户最终跟中介租房,完成操作。


实现

RentService

/**
 * 租房服务,相当于抽象的 Subject
 */
public interface RentService {

	/**
	 * 客户是否满意
	 */
    void rent(boolean isSatisfied);

}

Landlord

/**
 * 业主,相当于 RealSubject
 */
public class Landlord implements RentService{

    /**
     * 业主姓名
     */
    private String name;
    /**
     * 房屋位置
     */
    private String location;
    /**
     * 期望租金
     */
    private double rental;

    @Override
    public void rent(boolean isSatisfied) {
        if (isSatisfied) {
            System.out.println(String.format("业主 %s 收到中介短信:房屋出租成功", name));
        }
    }

    public Landlord(String name, String location, double rental) {
        this.name = name;
        this.location = location;
        this.rental = rental;
    }

    public String getName() {
        return name;
    }

    public String getLocation() {
        return location;
    }

    public double getRental() {
        return rental;
    }
}

Agency

/**
 * 中介,相当于 Proxy
 */
public class Agency implements RentService {

    /**
     * 业主
     */
    private Landlord landlord;
    /**
     * 期望租金
     */
    private double rental;

    public Agency(Landlord landlord) {
        this.landlord = landlord;
    }

    /**
     * 中介广告
     */
    public void advertisement() {
        System.out.println("中介广告:有一套" + landlord.getLocation() + "的房子准备出租,欢迎咨询!");
    }

    /**
     * 带客户看房
     */
    public void preRent(double income) {
        System.out.println("中介带领客户看房、谈价格...");
        this.rental = landlord.getRental() + income;
    }

    @Override
    public void rent(boolean isSatisfied) {
        advertisement();
        preRent(300);

        if (isSatisfied) {
            System.out.println(String.format("客户满意,决定租房,正在签订租房合同(租金:%f/月)...", rental));
            landlord.rent(isSatisfied);
            postRent();
        } else {
            System.out.println("客户不满意,租房失败,等待下个客户...");
        }
    }

    /**
     * 汇款
     */
    public void postRent() {
        System.out.println(String.format("中介正在给业主%s汇款租金(%f)...",landlord.getName(), landlord.getRental()));
    }

}

Client

public class Client {

    public static void main(String[] args) {
        // 业主将房子交给中介代理出租
        Landlord landlord = new Landlord("小张", "北京市海淀区颐和园路xxx小区", 1500);
        RentService rentService = new Agency(landlord);

        // 客户租房
        rentService.rent(true);
    }

}

---------------------输出---------------------
中介广告:有一套北京市海淀区颐和园路xxx小区的房子准备出租,欢迎咨询!
中介带领客户看房、谈价格...
客户满意,决定租房,正在签订租房合同(租金:1800.000000/)...
业主 小张 收到中介短信:房屋出租成功
中介正在给业主小张汇款租金(1500.000000)...

源码

Click here


总结

代理模式的使用场景有很多:

  1. 远程代理,这种方式通常是为了不同JVM中的类进行通信,例如 RMI。
  2. 虚拟代理,这种方式通常用于要创建的目标对象开销很大时。例如,下载一幅很大的图像需要很长时间,因某种计算比较复杂而短时间无法完成,这时可以先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感觉。
  3. 安全代理,这种方式通常用于控制不同种类客户对真实对象的访问权限。
  4. 智能指引,主要用于调用目标对象时,代理附加一些额外的处理功能。
  5. 延迟加载,指为了提高系统的性能,对于高资源消耗的对象进行延迟加载,在访问该对象时再对目标加载。例如,Hibernate 中就存在属性的延迟加载和关联表的延时加载。

装饰器模式和代理模式的比较
都是实现同一个接口,一个类包装另一个类。

装饰器模式:能动态的新增或组合对象的行为,在不改变接口的前提下,动态扩展对象的功能
代理模式:为其他对象提供一种代理以控制对这个对象的访问,在不改变接口的前提下,控制对象的访问

装饰模式是“新增行为”,而代理模式是“控制访问”。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值