【设计模式】

设计模式——代理模式

本片文章总结于《狂神说Java》的设计模式篇章:
B站链接

一、代理模式

简介:
代理模式是一种结构型的设计模式,为一个对象提供一个代理对象,然后可以通过使用代理对象来访问原始对象。(Spring AOP就是通过代理模式实现的)
类图:
在这里插入图片描述

  • 抽象主题:一般使用接口或者抽象类来实现
    -真实角色:被代理的对象
  • 代理角色Proxy:代理真实的角色;除了完成代理角色的工作,还会进行一些二附属的操作
  • 客户Client:使用代理角色来进行一些操作

二、具体实现

代理模式分为动态代理和静态代理,区别在于是在运行时期检查还是编译时期。(静态代理自己写,动态代理交给程序运行过程中自动创建

2.1. 静态代理

优点

  • 被代理对象可以更加专注于自己的行为操作,一些公共的额外的操作可以交由代理对象统一管理,实现业务的分工
  • 公共业务发生扩展的时候可以更加集中的管理

缺点

  • 一个真实角色就要产生一个代理对象,当程序中的需要代理的类比较多,则需要多个代理类,会使得程序结构庞大复杂

实现

Rent:抽象的角色,表示代理的行为(一般是接口或者抽象类)

// 抽象角色,即代理的行为
public interface Rent {
    void rent();
}

LandLord:真实角色,即需要代理的角色

// 需要代理的角色:房东
public class Landlord implements Rent {

    @Override
    public void rent() {
        System.out.println("房东需要租房");
    }
}

Proxy:代理角色,代理真实角色,除了完成真实角色的任务,还有一些自己的额外操作

// 代理角色
public class Proxy implements Rent{
    private Landlord landlord;
    public Proxy(){}
    public Proxy(Landlord landlord){
        this.landlord = landlord;
    }

    @Override
    public void rent() {
        // 其他的行为:看房
        seeHouse();
        // 代理的行为:租房
        landlord.rent();
        // 其他行为:签署合同
        contract();
        // 其他的行为:收取中介费
        fare();
    }
    private void seeHouse(){
        System.out.println("中介带你看房");
    }
    private void contract(){
        System.out.println("中介带你签合同");
    }
    private void fare(){
        System.out.println("中介收取中介费");
    }


}

Client:客户

public class Client {
    public static void main(String[] args) {
        // 房东要租房(只有一个出租房屋的行为)
        Landlord landlord = new Landlord();
        // 中介帮房东(出租房屋),并且还有其他行为(签合同、看房等)
        Proxy proxy = new Proxy(landlord);
        // 客户直接找房东租房
        proxy.rent();

    }
}

运行结果
在这里插入图片描述


2.2. 动态代理

优点:

  • 被代理对象可以更加专注于自己的行为操作,一些公共的额外的操作可以交由代理对象统一管理,实现业务的分工
  • 公共业务发生扩展的时候可以更加集中的管理
  • 在JVM运行时期动态构建对象和动态地调用代理方法,可以很好解决静态代理一个真实对象就需要一个代理类的缺点,它可以代理多个类。
    -动态代理的是某一类的业务

动态代理主要有JDK 动态代理(基于接口)和 Cglib 的动态代理(基于类),下文主要是基于JDK 的动态代理。

抽象主题

public interface Rent {
    void rent();
}

真实对象

public class Landlord implements Rent {

    @Override
    public void rent() {
        System.out.println("房东需要租房");
    }
}

代理对象,与静态代理不同我们不再主动写死真实对象,利用反射机制,实现InvocationHandler接口创建动态代理类,我们的代理对象使用的是Object,而不再是上面单一的Landlord,通过Proxy.newProxyInstance动态根据传入的target生成代理类,代理的行为则重写invoke方法,通过**method.invoke(tarhet , this)**来实现,代理类的其他行为可以加载invoke里面

public class ProxyInvocationHandle implements InvocationHandler {
    // 被代理的接口或者行为
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
    // 动态生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }

    // 处理代理的的业务逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("其他方法1");
        Object result = method.invoke(target, args);
        System.out.println("其他方法2");
        return result;
    }

Client

public class Client {
    public static void main(String[] args) {
        // 真实的角色(需要代理的人):房东
        Landlord landlord = new Landlord();
      
        // 获得代理角色
        ProxyInvocationHandle proxyHandle_rent = new ProxyInvocationHandle();
        // 设置代理对象(代理的内容)
        proxyHandle_rent.setTarget(landlord);
        Rent proxy_rent = (Rent) proxyHandle_rent.getProxy();
        proxy_rent.rent();
    }
}

运行结果
在这里插入图片描述

与静态代理不同的是,我们可以通过这个方法代理多个真实对象,或者多个主题:

新加主题:Arrange

public interface Arrange {
    void arrange();
}

真实对象:

public class Marry implements Arrange{
    @Override
    public void arrange() {
        System.out.println("结婚布置场所");
    }
}

Client:我们直接使用前面的ProxyInvocationHandle,而不需要重新写一个代理对象

public class Client {
    public static void main(String[] args) {
        // 真实的角色(需要代理的人):房东
        Landlord landlord = new Landlord();
        // 真实的角色(需要代理的人):结婚对象
        Marry marry = new Marry();
        // 获得代理角色
        ProxyInvocationHandle proxyHandle_rent = new ProxyInvocationHandle();
        // 设置代理对象(代理的内容)
        proxyHandle_rent.setTarget(landlord);
        Rent proxy_rent = (Rent) proxyHandle_rent.getProxy();
        proxy_rent.rent();

        ProxyInvocationHandle proxyHandle_arrange = new ProxyInvocationHandle();
        proxyHandle_arrange.setTarget(marry);
        Arrange proxy_marry = (Arrange) proxyHandle_arrange.getProxy();
        proxy_marry.arrange();

    }
}

结果:
在这里插入图片描述

类似的,同一个主题的不同实现类我们也可以用一个ProxyInvocationHandle去完成代理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值