Java 设计模式之代理模式

作者: adm 分类: java 发布时间: 2022-08-09

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

代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信。

在java中又分为静态代理和动态代理:

静态代理:静态代理的代理类在编译器就生成。

动态代理:动态代理的代理类在java运行时动态生成。

二、静态代理
举例:

比如在我们租房的时候,很难找到房东,只能找中介,此时中介就相当于代理类,房东为被代理的类,房东是租房的,中介也可以租房,而我们是通过中介与房东取得联系进行租房,而且中介还租了我中介费,这个收取中介费的过程就是代理类提供了额外的处理。接下来来看代码实现。

首先我们提供一个接口,并提供租房的方法。

租房接口:

public interface RentHouse {
    void rentHoust();
}

房东类:

public class Homeowner implements RentHouse {
    //实现租房方法
    @Override
    public void rentHoust() {
        System.out.println("房东租房");
    }
}

在这种情况下我们可以直接new Homeowner()来实现租房,但是一般情况下我们不能直接联系到房东,所以我们需要提供一个代理类,即中介类:

public class HomeProxy implements RentHouse {
    //房东类(中介类中持有房东类)
    private Homeowner homeowner = new Homeowner();

    @Override
    public void rentHoust() {
        System.out.println("中介收了点中介费");
        homeowner.rentHoust();
    }
}

使用:

        //创建中介对象
        HomeProxy homeProxy = new HomeProxy();
        //租房
        homeProxy.rentHoust();

输出:

中介收了点中介费
房东租房
至此静态代理模式就完成了,其原理就是中介持有房东对象,在客户租房时收了点中介费,然后再去联系房东租房。

三、动态代理
上面提到了动态代理的代理类在java运行时动态生成。那么怎么动态生成呢?在java中提供了一个静态代理类Proxy,并且提供了一个获取代理对象的静态方法newProxyInstance,接下来看代码:

租房接口:

public interface RentHouse {
    void rentHoust();
}

房东类:

public class Homeowner implements RentHouse {
    //实现租房方法
    @Override
    public void rentHoust() {
        System.out.println("房东租房");
    }
}

代理工厂类(通过此类获取代理对象):

public class ProxyFactory {
    //声明房东类
    private Homeowner homeowner = new Homeowner();

    public RentHouse getProxyObj(){
        //获取代理对象
        RentHouse rentHouse = (RentHouse) Proxy.newProxyInstance(
                homeowner.getClass().getClassLoader(),
                homeowner.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("中介收了点中介费");
                        Object result = method.invoke(homeowner,args);
                        return result;
                    }
                }
        );
        return rentHouse;
    }
}

使用:

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.getProxyObj().rentHoust();

输出:

中介收了点中介费
房东租房

在Proxy.newProxyInstance()中有三个参数:

ClassLoader loader(类加载器):加载代理类,通过目标对象获取。
Class[] interfaces:代理类实现的接口的字节码对象。
InvocationHandler h:代理对象的处理程序。

至此动态代理模式就完成了,其中通过ProxyFactory中的方法getProxyObj()中的Proxy.newProxyInstance动态获取了代理类。

代理模式在客户端和目标对象之前起到了一个中介和保护目标对象的作用,而且还可以扩展目标对象的功能,并使客户端和目标对象分离,降低了耦合性,但是缺点就是增加了程序的复杂度。

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!