什么是代理设计模式?了解静态代理和动态代理的区别?

一,代理设计模式

我们首先要了解代理的含义:代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。

简单点来说,是地区的经销商,也可以说是我们经常听到的中介。就比如说找中介租房子,中介负责一切事务,你只需要入住就可以了。如果委托A对象想访问一个目标C对象,就需要通过代理B对象去访问,代理B对象会进行一系列操作(确认,验证一下等)才会让委托A对象去访问目标C对象,也可以在委托A对象访问目标C对象之后进行一些代理操作。代理B对象可以实现在目标C对象代码不变的情况下,对访问前后进行一些操作。通俗来讲就是对目标C对象的访问控制。

二,静态代理

某个对象提供一个代理,代理角色固定,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。

代理接口:

//代理接口,处理给定的任务
public interface Subject{

   //执行给定的名字的任务 takeName

public void dealTask(String taskName);
}

委托类,具体事务处理:

//实现代理接口,执行任务的类
public class RealSubiect implements Subject{

//执行名字的任务,打印出任务名,并休眠500ms模拟任务执行很长时间 taskName
@Override
public void dealTask(String taskName){

  System.out.println("在执行任务:"+taskName);
  try{
    Thread.sleep(500);
  }catch (InterruptedException e){
        e.printStakTrace();
        }

    } 

}

静态代理类:

// 代理类,实现代理类接口
public class ProxySubject implements Subject {

//代理类持有一个委托类的对象引用
private Subject delegate;

public ProxySubject(Subject delegate){
    this.delegate  = delegate;
}

//将请求分派给委托类执行,记录任务执行前后的时间,时间差为任务处理的时间  taskName

@Override 
public void dealTask(String taskName){
    long stime = System.currentTimeMillis();
//将请求分派给委托类处理
    delegate.dealTask(taskName);
    long ftime = System.currentTimeMillis();
System.out.println("执行任务所用时间"+(ftime -stime)+"毫秒");
}
}

生成静态代理类工厂:

public class SubjectStaticFactory {

//客户类调用此方法获得代理对象
//对客户来讲,不知道返回的是什么对象
public static Subject getInstance(){
 return new ProxySubject(new RealSubject());

   }

}

客户类:

public class Client {
    public static void main(String[] args){
     Subject proxy = SubjectStaticFactory.getInstance();
     proxy.dealTask("DBQueryTask");
 
   }
}

静态代理实现的条件:

1、有共同的行为(房子) - 接口

2、目标角色(租房人) - 实现行为

3、代理角色(中介) - 实现行为 增强目标对象行为

静态代理的特点

1、目标角色固定

2、在应用程序执行前就得到目标角色

3、代理对象会增强目标对象的行为

4、有可能存在多个代理 引起"类爆炸"(缺点)

优点:安全性高 ,保证类的重用性

缺点:大量类接口,灵活性不强


 

三,动态代理

相比于静态代理,动态代理在创建代理对象上更加的灵活,动态代理类的字节码在程序运行时,由Java反射机制动态产生。它会根据需要,通过反射机制在程序运行期,动态的为目标对象创建代理对象,无需程序员手动编写它的源代码。动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为反射机制可以生成任意类型的动态代理类。代理的行为可以代理多个方法即满足生产需要的同时又达到代码通用的目的

动态代理实现的条件


动态代理能够实现代理类无需和被代理类直接关联,但是动态代理类必须实现Invocation接口,并且实现invoke() 方法,在invoke()方法中需要完成两件事情:一是添加服务,二是调用业务逻辑方法。代理服务就是在代理类中的invoke中执行的。我们可以通过反射机制获取目标对象的加载类、接口,还有实现了Invocation接口的代理类传到Proxy.newProxyInstance(被代理类,被代理类接口,代理类)方法中获取到代理类的对象实例。
 

动态代理的两种实现方式:

1. JDK 动态代理

2. CGLIB动态代理

创建自己调用的处理器

// 动态代理类对应调用处理程序
public class SubjectInvocatinHandler implements InvocationHandler {

//代理类持有一个委托类的对象引用
private Object delegate;

public SubjectInvocationHandler(Object delegate){
    this.delegate  = delegate;
}


@Override 
public void dealTask(String taskName){
    long stime = System.currentTimeMillis();

    //利用反射机制将请求分配给委托类处理
    //Method的invoke返回Object对象作为方法执行结果
    //因为示例程序无返回值忽略返回值

    method.invoke(delegate, args);
    long ftime = System.currentTimeMillis();
    System.out.println("执行任务所用时间"+(ftime -stime)+"毫秒");

    return null;
  }
}

生成动态代理工厂,列出如何生成动态代理对象类的步骤

// 生成动态代理对象工厂

public class DynProxyFactory {

//客户类调用此工厂方法获得代理对象
//对客户类来说,其并不知道哪个类对象

public static Subject getInstance(){
 Subject delegate = new RealSubject();
 InvocationHandler handler = new SubjectInvocationHandler(delegate);
 Subject proxy = null;
 proxy = (Subject)Proxy.newProxyInstance(
    delegate.getClass().getClassLoader(),
    delegate.getClass().getInterfaces(),
    handler);

  return proxy;
   }
}

客户类

public class Client {
    public static void main(String[] args){
     Subject proxy = DynProxyFactory.getInstance();
     proxy.dealTask("DBQueryTask");
 
   }
}

动态代理的特点

  1. 目标对象不固定
  2. 在应用程序执行时动态创建目标对象
  3. 代理对象会增强目标对象的行为

优点:降低了代码的冗余度,较强灵活性

缺点:需要实现接口(Proxy已经设计得非常完美,但还是无法摆脱仅支持interface代理)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值