java设计模式之代理模式

一,静态代理
代理的好处是:我们在调用时候,可以不用直接操作目标类,而是使用的代理类,使用代理类的好处是:我们可以对代理类添加一些额外的方法,这样就是对目标类进行了增强。代理有三个角色
1,抽象角色,是一个接口(或者抽象类),代理角色,和真实角色都要实现此接口。
2,真实角色:具备各种功能(方法)的一个类
3,代理角色:持有真实角色的引用(成员变量),还可以有自己的功能(方法)。


1,首先看的是抽象角色:CommonInterface.java


package proxy;
/**抽象角色:为一个接口或者抽象类,代理角色和真实角色都要实现此接口,这里以生产红酒来举例*/
public interface CommonInterface{
	/** 生产红酒的方法 */
	public void product();
	/**销售红酒的方法*/
	public void sell();
}

2,真实角色:RealObject.java
package proxy;
/**真实角色,实际上要完成的各种功能都是在此类中实现的*/
public class RealObject implements CommonInterface{
	
	public void product(){
		System.out.println("生产红酒。。。");
	}
	
	public void sell(){
		System.out.println("销售红酒。。。");
	}
}

3,代理角色:ProxyObject.java
package proxy;

/** 代理角色:实际上调用的时候调用的是代理角色,在代理角色内部,来调用真实角色的各种方法,真实角色对我们调用者来说是不可见的 */
public class ProxyObject implements CommonInterface{
	private RealObject realObject = new RealObject();// 代理角色要持有真实角色的引用。这里为了方便直接在此处实例化new出对象,可以在此类的构造方法或者需要的地方实例化


	@Override
	public void product() {
		before();//调用realObject.product()是我们的本来目的,这里我们还可以调用before()实际上是对product()方法进行增强了,提供了额外的功能。这里就是一个简单的AOP实现了
		realObject.product();//可以看出就是在代理对象的方法的内部调用真实对象的方法的,
		after();//功能同 before()
	}


	@Override
	public void sell() {
		before();
		realObject.sell();
		after();


	}


	/** 代理角色自己的方法 */
	public void before() {
		System.out.println("before....");
	}


	/** 代理角色自己的方法 */
	public void after() {
		System.out.println("after....");
	}
}

4,客户端调用:ProxyTest.java


package proxy;

import static org.junit.Assert.*;

import org.junit.Test;

public class ProxyTest {

	@Test
	public void test() {
		ProxyObject proxyObject=new ProxyObject();
		proxyObject.product();//调用代理对象,可以看出我们想生产红酒,并没有调用 RealObject中的product()方法,
								//而是通过代理对象来间接调用的,同时通过代理对象,还调用了before()after()等额外的方法
		proxyObject.sell();
	}

}

ProxyTest.java 输出

before....
生产红酒。。。
after....
before....
销售红酒。。。
after....

二,JDK动态代理

动态代理的对象必须要实现接口,换句话说只能代理实现接口的对象,和静态代理相比目标类需要实现接口,而代理类不需要实现接口

1,首先创建接口类:PersonService.java

package dynamicproxy;

public interface PersonService {
	public void say(String word);
	public void run(String speed,String where);
}

2,创建目标类PersonServiceImpl.java 实现以上接口

package dynamicproxy;

public class PersonServiceImpl implements PersonService {

	@Override
	public void say(String word) {
		System.out.println("say..."+word);

	}

	@Override
	public void run(String speed,String where) {
		System.out.println("run..."+speed+where);

	}

}
3,创建代理类ProxyFactoryBean.java,此代理类要实现InvocationHandler接口

package dynamicproxy;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**代理类*/
public class ProxyFactoryBean implements InvocationHandler {
private Object obj;//代理类持有的对被代理对象的引用。(被代理对象)

/** 
 * 生成代理对象
 * @param obj 从外部传入的被代理的对象
 * @return 返回一个被代理好的对象(代理对象)
 */
public Object createProxyInstance(Object obj){
this.obj=obj;
//生成代理类的字节码加载器   
ClassLoader loader=obj.getClass().getClassLoader();
//获得被代理对象obj的所有接口
Class<?>[] objInterfaces=obj.getClass().getInterfaces();
//返回生成的代理对象,这里要用到Proxy的方法,this表示InvocationHandler对象
return Proxy.newProxyInstance(loader, objInterfaces, this);
}

/**
 * @param proxy 代理对象
* @param method 要调用的方法
 * @param args 方法参数。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("开始。。。");
// 调用被代理类的方法,传入参数args,得到返回
//jdk动态代理是根据java反射来实现的,会根据入参的个数和类型,自动调用相应的方法
Object object=method.invoke(obj, args);
System.out.println("结束。。。");
return object;
}

}
 4,创建测试类DynamicProxyTest.java 

package dynamicproxy;

import static org.junit.Assert.*;

import org.junit.Test;

public class DynamicProxyTest {

	@Test
	public void test() {
		ProxyFactoryBean proxyFactoryBean=new ProxyFactoryBean();
		//返回代理对象
		PersonService personService=(PersonService) proxyFactoryBean.createProxyInstance(new PersonServiceImpl());
		//jdk动态代理是根据java反射来实现的,会根据入参的个数和类型,自动调用相应的方法
		personService.say("hello word");
		personService.run("20", "beijing");
	}

}
5,输出为

开始。。。
say...hello word
结束。。。
开始。。。
run...20beijing
结束。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值