设计模式之代理模式

1.代理模式的介绍

代理模式(Proxy Pattern)也称为委托模式,是结构型设计模式的一种。在我们生活中代理模式是非常常见的,比如我们让同事帮忙买饭,房屋中介等都是一种代理模式。也就是让别人给自己干活。

2.代理模式的定义

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

3.代理模式的UML类图

设计模式之代理模式_第1张图片

  • Subject: 抽象角色指真实角色和代理角色共有的接口。
  • RealSubject: 真实角色需要实现抽象接口,定义真实角色所要实现的业务逻辑,以供代理角色调用。
  • ProxySubject: 代理角色也需要实现抽象接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。

4.静态代理模式的实现

通过让朋友代买水果,来实现代理模式:
第一步:先创建一个买水果的接口 (抽象角色)

package com.monkey.designmode.proxy;
/**
 * Created by Monkey on 2020/5/9.
 * Description:  买水果的接口
 */
public interface IBuyFruit {
    void buyFruit();
}

第二步:实现买水果的接口 (真实角色)

package com.monkey.designmode.proxy;

/**
 * Created by Monkey on 2020/5/9.
 * Description:  具体的实现类,实现买水果的接口
 */
public class Monkey implements IBuyFruit {
    @Override
    public void buyFruit() {
        System.out.println("我在果园里买水果");
    }
}

第三步:创建一个代理对象 (代理角色)

package com.monkey.designmode.proxy;

/**
 * Created by Monkey on 2020/5/9.
 * Description:代理类 持有一个被代理者的引用
 */
public class BuyFruitProxy implements IBuyFruit {

    private IBuyFruit iBuy;

    public BuyFruitProxy(IBuyFruit iBuy) {
        this.iBuy = iBuy;
    }

    @Override
    public void buyFruit() {
        iBuy.buyFruit();
    }
}

客户端

package com.monkey.designmode.proxy;

public class ProxyClient {
    public static void main(String[] args) {
        IBuyFruit monkey = new Monkey();
        BuyFruitProxy proxy = new BuyFruitProxy(monkey);
        proxy.buyFruit();
    }
}

这就是一个简单的静态代理模式,真实对象将方法的执行委托给代理对象去完成。

5.动态代理模式的实现

我们在静态代理的基础上实现动态代理模式,在这里我们需要创建一个动态处理器,帮我们创建一个代理类,而不需要静态代理中的 BuyFruitProxy 代理类了。动态代理是在运行时利用反射的机制动态生成代理者的对象。

创建一个动态代理类

package com.monkey.designmode.proxy;

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

/**
 * Created by Monkey on 2020/5/9.
 * Description:动态代理类
 */
public class DynamicProxy implements InvocationHandler {
    private Object object;

    public DynamicProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用被代理对象的方法
        Object result = method.invoke(object,args);
        return result;
    }
}

在动态代理类中我们声明一个Object的引用,指向被代理类,我们调用被代理类的具体方法在invoke()方法中执行。
客户端

package com.monkey.designmode.proxy;

import java.lang.reflect.Proxy;

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

        IBuyFruit monkey = new Monkey();
        //构造一个动态代理
        DynamicProxy dynamicProxy = new DynamicProxy(monkey);
        ClassLoader classLoader = monkey.getClass().getClassLoader();
        //动态构造一个代理者
        IBuyFruit  proxy = (IBuyFruit) Proxy.newProxyInstance(classLoader,
                new Class[]{IBuyFruit.class},dynamicProxy);
        proxy.buyFruit();
    }
}

Proxy.newProxyInstance()方法接受三个参数:

  • ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的
  • Class[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
  • InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法

使用动态代理很好的对代理者与被代理者进行解耦,使两者之间没有了直接的耦合;其中静态代理只能对给定的接口下的实现类做代理。而静态代理更符合面向对象的原则。

6.总结

通过引入代理对象的方式间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性。通过代理对象对原有的业务增强,而不影响原有的业务。

我们用通俗易懂的方式来理解下静态代理和动态代理的区别,我们在需要别人帮忙的时候,会提前给别人说好之后,才会给我们帮忙,这就是静态代理模式;而我们在需要帮忙的时候,直接告诉别人,现在就给我帮忙,这就是动态代理模式。

你可能感兴趣的:(java学习)