Java代理模式整理

代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着“中间人”的角色。

1.java代理的基本构成

  1. 抽象角色:声明真实对象和代理对象的共同接口,这样在任何使用真实对象的时候都可以使用代理对象。
  2. 代理角色:代理角色内部含有真实角色的引用,从而可以在任何适合操作真实对象。
  3. 真实角色:即为代理对象所代表的目标对象,代理角色所代表的真实对象,是我们最终要引用的对象。

2.静态代理

interface Subject//抽象角色
{  
    public void doSomething();  
}
class RealSubject implements Subject//真实角色
{  
    public void doSomething()  
  {  
    System.out.println( "call doSomething()" );  
  }  
}
class SubjectProxy implements Subject//代理角色
{
  //代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。
  Subject subimpl = new RealSubject();
  public void doSomething()
  {
     System.out.println("before"); //调用目标对象之前可以做相关操作
     subimpl.doSomething();
     System.out.println("after");//调用目标对象之后可以做相关操作
  }
}
 
public class Test
{
    public static void main(String[] args) throws Exception
    {
        Subject sub = new SubjectProxy();
        sub.doSomething();
    }
}

可以看到,SubjectProxy实现了Subject接口(和RealSubject实现相同接口),并持有的是Subject接口类型的引用。这样调用的依然是doSomething方法,只是实例化对象的过程改变了,结果来看,代理类SubjectProxy可以自动为我们加上了before和after等我们需要的动作。

如果将来需要实现一个新的接口,就需要在代理类里再写该接口的实现方法,对导致代理类的代码变得臃肿;另一方面,当需要改变抽象角色接口时,无疑真实角色和代理角色也需要改变。

3.动态代理

Java的动态代理比静态代理的思想更向前迈进了一步,因为它可以动态的创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。

interface Subject  
{  
    public void doSomething();  
}
class RealSubject implements Subject  
{  
    public void doSomething()  
  {  
     System.out.println( "call doSomething()" );  
  }  
}
class ProxyHandler implements InvocationHandler
{
    private Object tar;
    //绑定委托对象,并返回代理类
    public Object bind(Object tar)
    {
        this.tar = tar;
        //绑定该类实现的所有接口,取得代理类
        return Proxy.newProxyInstance(tar.getClass().getClassLoader(),
                                      tar.getClass().getInterfaces(),
                                      this);
    }   
    public Object invoke(Object proxy , Method method , Object[] args)throws Throwable//不依赖具体接口实现
    {
        Object result = null;//被代理的类型为Object基类
        //这里就可以进行所谓的AOP编程了
        //在调用具体函数方法前,执行功能处理
        result = method.invoke(tar,args);
        //在调用具体函数方法后,执行功能处理
        return result;
    }
}
public class Test
{
    public static void main(String args[])
    {
           ProxyHandler proxy = new ProxyHandler();
           //绑定该类实现的所有接口
           Subject sub = (Subject) proxy.bind(new RealSubject());
           sub.doSomething();
    }
}

在调用过程中使用了通用的代理类包装了RealSubject实例,然后调用了Jdk的代理工厂方法实例化了一个具体的代理类。最后调用代理的doSomething方法,还有附加的before、after方法可以被任意复用(只要我们在调用代码处使用这个通用代理类去包装任意想要需要包装的被代理类即可)。当接口改变的时候,虽然被代理类需要改变,但是我们的代理类却不用改变了。这个调用虽然足够灵活,可以动态生成一个具体的代理类,而不用自己显示的创建一个实现具体接口的代理类。

参考:https://www.cnblogs.com/LCcnblogs/p/6823982.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VI仔爱学习

让我看看是谁在学习

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值