Java设计模式之静态代理和动态代理(简单例子)

1、代理模式

一个生活中的例子:明星都有一个自己的经纪人,这个经纪人就是他们的代理人。
当我们需要找明星表演时,不能直接找到该明星,只能是找明星的代理人。比如张学友在没有出名之前,我们可以直接找他唱歌,跳舞,拍戏;但是张学友出名之后,他干的第一件事就是找一个经纪人,这个经纪人就是张学友的代理人(代理)。
当我们需要找刘德华表演时,不能直接找到张学友了,只能是找其代理人,具体事务和代理人谈,相当于和张学友本人洽谈。张学友这个代理人存在的价值就是拦截我们对张学友的直接访问

这个现实中的例子和我们在开发中是一样的,我们在开发中之所以要产生一个对象的代理对象,主要用于拦截对真实业务对象的访问。那么代理对象应该具有什么方法,代理对象应该具有和目标对象相同的方法。

一个典型的代理模式通常有三个角色(代理三要素)

  • 接口,接口中的方法是要真正去实现的
  • 被代理类,实现上述接口,这是真正去执行接口中方法的类
  • 代理类,帮助被代理类去实现方法

2、静态代理

若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类。

(1)共同接口

public interface Action {
    void sing(String name);//唱歌
}

(2)真实对象

public class Star implements Action{//明星
    @Override
    public void sing(String name){
        System.out.println("下面为大家演唱:"+name);
    }
}

(3)代理人

public class Proxy implements Action{
    private Action person;

    public Proxy(Action person) {
        this.person = person;
    }

    @Override
    public void sing(String name) {
        System.out.println("代理人通知明星:");
        person.sing(name);
    }
}

(4)测试

public class Main {
    public static void main(String[] args) {
        Proxy proxy = new Proxy(new Star());
        proxy.sing("饿狼传说");
    }
}

(5)运行结果

代理人通知明星:
下面为大家演唱:饿狼传说

3、动态代理

静态代理的局限在于运行前必须编写好代理类(当多个对象需要代理时,需要事先定义好对应代理类)。
动态代理的目的就是为了解决静态代理的不足,动态代理的代理类是在程序运行期间动态生成的。

使用动态代理的五大步骤

  1 通过实现InvocationHandler接口来自定义自己的InvocationHandler。

  2 通过Proxy类的getProxyClass方法获取代理类。

  3 通过反射机制获取代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)。

  4 将目标对象作为参数传入,通过构造方法获取自定义的InvocationHandler实例对象。

  5 将自定义的InvocationHandler实例对象作为参数传入,通过构造方法获取代理对象。

  6 代理对象调用目标方法。

package dynamic;

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

public class DynamicProxyHandler implements InvocationHandler {
    private Object person;

    public DynamicProxyHandler(Object person) {
        this.person = person;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //代理扩展逻辑
        System.out.println("代理人通知被代理人:");
        return method.invoke(person, args);
    }
}
package dynamic;

import java.lang.reflect.Proxy;
import proxy.Action;
import proxy.Star;

public class DynamicProxyDemo {
    public static void main(String[] args) {
        Star star = new Star();
        Action proxy = (Action)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Action.class}, new DynamicProxyHandler(star));
        proxy.sing("饿狼传说");
    }
}

Proxy.newProxyInstance 传入的是一个ClassLoader, 一个代理接口,和我们定义的handler,返回的是一个Proxy的实例。
运行结果

代理人通知被代理人:
下面为大家演唱:饿狼传说
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值