设计模式之代理模式

184 阅读2分钟

代理模式为对象提供一种代理,以控制这个对象的访问。代理模式分为静态代理和动态代理。

一、静态代理

静态代理的实现,有一个接口和一个实现了这个接口的实体类,一般分别称之为抽象角色和真实角色。另有一个代理类,称之为代理角色,代理真实角色后,会做一些附属操作。

首先建立一个接口,留学StudyAbroad,然后建立一个实现这个接口的类,学生Student,然后建立一个代理Proxy,通过这个代理去代理学生,代理的时候,可以在原有类的基础上增加一些代理类才能做的操作。在测试类里面完成一些操作。

//留学的接口
public interface StudyAbroad {
    void studyAbroad();
}

//学生要留学
public class Student implements StudyAbroad{

    @Override
    public void studyAbroad() {
        System.out.println("学生要出过留学");
    }
}

//通过组合的方式代理学生
public class Proxy implements StudyAbroad{
    private Student student;

    public Proxy() {}

    public Proxy(Student student) {
        this.student = student;
    }

    /**
     * 帮助学生出过留学
     */
    @Override
    public void studyAbroad() {
        student.studyAbroad();
        fare();
    }
    
    public void fare() {
        System.out.println("收取中介费");
    }
}

//测试
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        Proxy proxy = new Proxy(student);
        proxy.studyAbroad();
    }
}

静态代理中,一个实现类必须有一个对应的代理,随着代码量增大,代码会变得非常冗余。我们可以用动态代理解决这个问题。

二、动态代理

动态代理的代理类是动态生成的,而不是直接写好的。动态代理分为两大类,基于接口的动态代理(JDK动态代理)和基于类的动态代理(cglib动态代理)。JDK动态代理,主要是实现InvocationHandler接口并重写其中的invoke()方法,再通过Proxy的newProxyInstance方法获得代理类。

//用这个类自动生产代理类
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成,得到代理类
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target, args);
        fare();
        return result;
    }

    public void fare() {
        System.out.println("交中介费");
    }
}
public static void main(String[] args) {
    //真实角色
    Student student = new Student();

    //代理角色
    ProxyInvocationHandler handler = new ProxyInvocationHandler();
    handler.setTarget(student);
    StudyAbroad proxy = (StudyAbroad) handler.getProxy();
    proxy.studyAbroad();
}