设计模式——代理模式(静态、动态)

        代理模式是常用的Java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

  代理类可以分为静态代理和动态代理。

1.静态代理

 由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

程序示例:

step1:定义委托类

public interface Email {
    public void send();
    public void receive();
}
public class FlashEmail implements Email {

	@Override
	public void send() {
		// TODO Auto-generated method stub
            System.out.println("邮件发送中。。。。。");
	}

	@Override
	public void receive() {
		// TODO Auto-generated method stub
       System.out.println("邮件接受中..........");
	}

}

step2:定义代理类,与委托类有同样的接口

  不改变原接口实现类的情况下,就可以对接口的功能进行需求变更

public class EmailProxy implements Email {

	Email email;
     //传入委托类初始化代理类
	public EmailProxy(Email email)
	{
		this.email=email;
	}
	@Override
	public void send() {

            System.out.println("发送邮件前准备。。。");
            email.send();
            System.out.println("发送后。。。。。。");
	}

	@Override
	public void revieve() {
		
		System.out.println("接受邮件前准备。。。"); 
		email.receive();
		System.out.println("接受邮件成功....");
	}

}

step3:测试代码:

public class Main {

	public static void main(String[] args) {
		//原始对象
	   Email email=new FlashEmail();
	   //接口的代理类
	   EmailProxy ep=new EmailProxy(email);
	   ep.send();
	   System.out.println("-----------------------------------------");
	   ep.receive();
	}
}

测试结果:

发送邮件前准备。。。
邮件发送中。。。。。
发送后。。。。。。
-----------------------------------------
接受邮件前准备。。。
邮件接受中..........
接受邮件成功....
 

2 动态代理

     动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。

    java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。这一个类和接口是实现我们动态代理所必须用到的。

(1)Proxy类

   Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法: 

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
throws IllegalArgumentException

参数说明

  • ClassLoader loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
  • Class<?>[] interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给  它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
  • InvocationHandler h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个    InvocationHandler对象上

(2)InvocationHandler 接口

IInvocationHandler是由代理实例的调用处理程序实现的接口 。每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。

       如果想要完成动态代理,首先需定义一个InvocationHandler接口的子类,以完成代理要完成的具体操作。下面介绍InvocationHandler 接口的 invoke 方法,我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用!

Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
  • proxy:  指代我们所代理的那个真实对象
  • method:  指代的是我们所要调用真实对象的某个方法的Method对象
  • args:  指代的是调用真实对象某个方法时接受的参数

程序示例:

step1:定义委托类

public interface Email {
    public void send();
    public void revieve();
}
public class FlashEmail implements Email {

	@Override
	public void send() {
		// TODO Auto-generated method stub
            System.out.println("邮件发送中。。。。。");
	}

	@Override
	public void revieve() {
		// TODO Auto-generated method stub
       System.out.println("邮件接受中..........");
	}

}

step2:在使用动态代理时,我们需要定义一个位于代理类与委托类之间的中介类,也叫动态代理类,以完成代理要完成的具体操作,这个类被要求实现InvocationHandler接口:

public class MyInvocationHandler implements InvocationHandler {

	Object obj;//委托对象
	
	public MyInvocationHandler(Object obj) {
		super();
		this.obj = obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		if("send".equals(method.getName())) {
			 System.out.println("发送邮件前准备。。。");
			 method.invoke(obj);//从委托对象中,调用该对象的指定方法,这里相当于send方法
		     System.out.println("发送后。。。。。。");
		}
		if("receive".equals(method.getName())) {
			System.out.println("接受邮件前准备。。。"); 
			method.invoke(obj);
			System.out.println("接受邮件成功....");
		}

		return null;
	}

}

step3:定义代理类工厂,用于动态生成代理类

public class ProxyFactory {
   Object obj;
   
   public ProxyFactory(Object obj) {
	super();
	this.obj = obj;
}

   public static Object createProxy(Object obj) 
   {
	MyInvocationHandler mch=new MyInvocationHandler(obj);
	return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), mch);
   }
}

step4:测试

public class Main {

	public static void main(String[] args) {
		Email email=new FlashEmail();
		Email emailProxy=(Email) ProxyFactory.createProxy(email);
		emailProxy.send();
		System.out.println("---------------------------------------------------");
		emailProxy.receive();
	}

}

测试结果:

发送邮件前准备。。。
邮件发送中。。。。。
发送后。。。。。。
-----------------------------------------
接受邮件前准备。。。
邮件接受中..........
接受邮件成功....

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值