01-设计模式-代理模式

cywdder / 2023-07-15 / 原文

1、代理模式的分类

代理模式分为:

静态代理:在编译阶段确定了被代理对象的类型,简单。
动态代理:在运行阶段确定了被代理对象的类型,复杂。

2、静态代理

静态代理涉及的类:

  1. 一个接口,下面的例子中命名为Subject
  2. 实现了接口的 被代理对象RealSubject
  3. 实现了接口的 代理对象StaticProxy

1、接口Subject-代码实现:

public interface Subject{
    void doSth();
}

2、被代理对象RealSubject-代码实现:

public class RealSubject implements Subject{
    @Override
    public void doSth(){
         System.out.println("\t\t被代理的对象执行 doSth() 方法");
    }
}

3、代理对象StaticProxy-代码实现:

public class StaticProxy implements Subject{
    private Subject subject;
    
    public StaticProxy(Subject subject) {
        this.subject = subject;
    }
    
    @Override
    public void doSth(){
        System.out.println("静态代理-前置方法...");
        subject.doSth();
        System.out.println("静态代理-后置方法...");
    }
}

4、使用:

public class Main {
    public static void main(String[] args) {
        /*
           静态代理:
             - 在编译时就确定了代理关系。
             - 代理类和被代理类实现共同的接口,
               被代理类作为代理类的成员变量,
               在代理类的重写的方法里调用被代理类的方法。
         */        
        RealSubject subject = new RealSubject();
        StaticProxy proxy = new StaticProxy(subject);
        proxy.doSth();
    }
}

/* 
打印结果:

        静态代理-前置方法...
                被代理的对象执行 doSth() 方法
        静态代理-后置方法...
        
*/

3、动态代理

动态代理涉及的类:

  1. 一个接口,下面的例子中命名为Subject
  2. 实现了接口的 被代理对象RealSubject
  3. 实现了接口的 代理对象DynamicProxyHandler

1、接口Subject-代码实现:

public interface Subject{
    void doSth();
}

2、被代理对象RealSubject-代码实现:

public class RealSubject implements Subject{
    @Override
    public void doSth(){
         System.out.println("\t\t被代理的对象执行 doSth() 方法");
    }
}

3、代理对象DynamicProxy-代码实现:

class DynamicProxyHandler implements InvocationHandler{
    
    private Subject subject;
    
    public DynamicProxyHandler(Subject subject) {
        this.subject = subject;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
        System.out.println("动态代理-前置方法...");
        Object rst = method.invoke(target, args);
        System.out.println("动态代理-后置方法...");

        return rst;
    }
    
}

4、使用:

import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        /*
            动态代理:
                - 在运行阶段确定调用关系,此处使用JDK的动态代理,jdk动态代理必须实现接口才能完成
                - 被代理类实现自定义接口,
                  被代理类作为代理处理器类的成员变量,
                  代理处理器类实现 InvocationHandler 接口,实现invoke方法,
                  invoke方法中执行 method.invoke(被代理类, args) 并返回代理对象
        */  
        
        Subject subject = new RealSubject();
        
        DynamicProxyHandler handler = new DynamicProxyHandler(subject);
        
        Subject proxy = (Subject)Proxy.newInstance(
        	subject.class.getClassLoader(),
            subject.class.getInterfaces(),
            handler
        );
        
        proxy.doSth();
                  
	}
}

/*
打印结果:

    动态代理-前置方法...
            被代理的对象调用 doSth() 方法
    动态代理-后置方法...
    
*/