设计模式(五):代理模式


prtyaa
prtyaa 2023-12-28 16:17:44 63069
分类专栏: 资讯

来看普通的代码:房东出租房屋,代码没毛病

 

来看静态代理:

Rent.java和HouseOwner.java不变,增加Proxys.java,然后测试

在静态代理中,房东HouseOwner是(真实的角色)被代理的角色,而Proxys是代理房东去出售房屋的,所以Proxys是代理对象。可以看出 真实对象和代理对象都实现了Rent接口(出租房子的接口)。并且代理对象中保存了真实对象的引用。

当然也可以这样,Proxys类里保存接口。面向对象的特性,在new Proxys类的对象的时候,可以传入接口的实现类,多态特性,接口指向实现类。

再来一个真实项目中的例子,方便理解静态代理:

也就是说真实对象和代理对象都要实现同一接口,UserService, 和之前租房的例子一样,都要实现Rent接口。然后代理类里保存一线接口的引用或者真实对象的引用,毕竟多态,真实对象也是实现了接口的。


接下来看一下动态代理:

动态代理和静态代理的区别:

静态代理的代理类是开发人员需要手动写,
而动态代理的代理类是动态生成的。

动态代理的分类:

基于接口的代理  JDK动态代理
基于类的代理    cglib

在这里需要了解一个类和一个接口:

Proxy类和invocationHandler接口,不知道的可以去文档里查一下这两个。

用动态代理改造租房例子,HouseOwner和 Rent接口不变 ,新增一个类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 本类的作用是动态生成代理
public class MyInvocationHandler implements InvocationHandler {

    // 被代理的接口
    private Rent rent;

    // 构造方法
    public MyInvocationHandler(Rent rent) {
        this.rent = rent;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance
                (rent.getClass().getClassLoader(),
                        rent.getClass().getInterfaces(),
                        this);

    }

    // invoke属于自动调用的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        see();
        Object result = method.invoke(rent, args);
        charge();
        return result;
    }

    public void see(){
        System.out.println("中介带想要租房的人看房");
    }
    public void charge(){
        System.out.println("中介收钱");
    }
}

测试类:

public class Test {
    public static void main(String[] args) {

        HouseOwner houseOwner = new HouseOwner();

        MyInvocationHandler handler =
                new MyInvocationHandler(houseOwner);

        Rent proxy = (Rent) handler.getProxy();
        proxy.rent();


    }
}

结果:


下来改造成公用的,不能是保存Rent接口了,必须是传什么接口,就替实现了那个接口的真实对象动态生成代理对象;代码如下

然后再改写一下 UserService 采用动态代理,使得执行add和delete方法执行之前和之后,都打印一下执行xxx方法之前和执行xxx方法之后。

如果改一下 Test类的 proxy.delete()

这样的话 ,UserServiceImpl类并没有改动代码,UserService接口的代码也没有变,却增加了业务的功能,可以把这个xxx方法执行之前 和 xxx方法执行之后,做成事务控制和日志,或者做成自己想要的功能都可以。这个就是jdk的动态代理

有些小伙伴会问了,那可不可以代理多个类呢?

当然可以,想一下假如还有个类也是实现了UserService这个接口,那么测试代码还是不变的,因为 UserService userService = new xxx() ,这个xxx实现了UserService接口,接口保存实现类对象,动态代理代理的是实现了接口的那些真实类的对象,多态的运用很奇妙。

其实换个思维来想,设计模式就是把类,抽象类,接口,这些面向对象,面向接口组合起来,如果java基础扎实,那么设计模式必须看得懂。

网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。

本文链接:https://www.xckfsq.com/news/show.html?id=31792
赞同 0
评论 0 条