Java 杂谈

Java设计模式之代理模式

2018-11-17  本文已影响38人  giants_one

前言

代理模式也被称为委托模式,它是结构型设计模式的一种。在现实生活中我们用到类似代理模式的场景有很多,比如代理上网、打官司等。

定义

为其他对象提供一种代理以控制对这个对象的访问。

角色

类型

从编码角度分类

从适用范围分类

静态代理模式的简单实现

场景描述

我多年没有回哈尔滨了,很想念哈尔滨的秋林红肠味道。但是本人因为工作一直很忙抽不开身,不能够亲自回哈尔滨购买,于是就拜托在哈尔滨的朋友帮我购买秋林红肠。

  1. 抽象主题类:抽象主题类具有真实主题类和代理的共同接口方法 buy
public interface IShop {
    void buy();
}
  1. 真实主题类:这个购买者 Giants 就是我,实现了 IShop 接口提供的 buy 方法。
public class Giants implements IShop {
    @Override
    public void buy() {
        System.out.println("购买");
    }
}
  1. 代理类:我找的代理类同样也要实现 IShop 接口,并且要持有被代理者,在 buy 方法中调用了被代理者的 buy 方法。
public class Purchasing implements IShop {
    private IShop mShop;

    public Purchasing(IShop shop) {
        this.mShop = shop;
    }

    @Override
    public void buy() {
        mShop.buy();
    }
}
  1. 客户端类:客户端类的代码就是包含了真实主题类(被代理者),最终调用的都是真实主题类(被代理者)实现的方法。
public class Client {
    public static void main(String[] args) {
        IShop giants = new Giants();
        IShop purchasing = new Purchasing(giants);
        purchasing.buy();
    }
}

动态代理模式的简单实现

场景描述

上面的例子是一个静态的代理,在代码运行前已经存在了代理类的 class 编译文件;而动态代理则是在带来运行时通过反射来动态地生成代理类的对象,并确定到底代理谁。我们在编码阶段无需知道代理谁,代理谁将会在代码运行时觉定。

  1. 创建动态代理类
/**
 * 实现Java提供的动态代理接口 InvocationHandler ,实现该接口需要重写 invoke 方法
 */
public class DynamicPurchasing implements InvocationHandler {
    private Object obj;

    public DynamicPurchasing(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(obj, args);
        if(method.getName().equals("buy")){
            System.out.println("Giants在买买买");
        }
        return result;
    }
}
  1. 修改客户端类代码如下:调用 Proxy.newProxyInstance 来生成动态代理类,调用 purchasingbuy 方法会调用 mDynamicPurchasinginvoke 方法。
public class Client {
    public static void main(String[] args) {
        //创建 Giants
        IShop giants = new Giants();
        //创建动态代理
        DynamicPurchasing mDynamicPurchasing = new DynamicPurchasing(giants);
        //创建 giants 的 ClassLoader
        ClassLoader loader = giants.getClass().getClassLoader();
        //动态创建代理类
        IShop purchasing = (IShop) Proxy.newProxyInstance(loader, new Class[] {IShop.class}, mDynamicPurchasing);
        purchasing.buy();
    }
}

优点

上一篇 下一篇

猜你喜欢

热点阅读