staticProxy(静态代理):
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。
比如请明星唱歌,不是直接找明星,而是找明星经纪人,出核心动作(唱歌)外,其他动作(面谈,签合同,订票,收尾款等)都由经纪人完成。
明星类和明星代理类都实现star接口:
package ProxyPattern_代理模式.StaticProxy;
public interface Star {
/** 面谈 */
void confer();
/** 签合同 */
void signContract();
/** 订票 */
void bookTicket();
/** 唱歌 */
void sing();
/** 收尾款 */
void collectMoney();
}
package ProxyPattern_代理模式.StaticProxy;
public class RealStar implements Star{
@Override
public void bookTicket() {
System.out.println("RealStar.bookTicket()");
}
@Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
}
@Override
public void confer() {
System.out.println("RealStar.confer()");
}
@Override
public void signContract() {
System.out.println("RealStar.signContract()");
}
@Override
public void sing() {
System.out.println("RealStar.sing()");
}
}
package ProxyPattern_代理模式.StaticProxy;
/**
* 代理类--代理处理唱歌,其他都会,因此new一个RealStar
* @author 11218
*
*/
public class ProxyStar implements Star{
private Star star;
public ProxyStar(Star Star) {
this.star = Star;
}
public ProxyStar() {
}
@Override
public void bookTicket() {
System.out.println("ProxyStar.bookTicket()");
}
@Override
public void collectMoney() {
System.out.println("ProxyStar.collectMoney()");
}
@Override
public void confer() {
System.out.println("ProxyStar.confer()");
}
@Override
public void signContract() {
System.out.println("ProxyStar.signContract()");
}
@Override
public void sing() {
star.sing();
}
}
客户端调用:
package ProxyPattern_代理模式.StaticProxy;
public class Client {
public static void main(String[] args) {
Star star = new RealStar();
Star proxy = new ProxyStar(star);
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();
proxy.collectMoney();
}
}
优缺点:
1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象 都要维护.
2.因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象 都要维护.
动态代理(dynamicProxy):
关键:
创建一个动态代理类,实现
InvocationHandler
接口,并重写该
invoke
方法。
创建动态代理的对象,需要借助
Proxy.newProxyInstance
。
该方法的三个参数分别是:
ClassLoader loader表示当前使用到的appClassloader。
Class<?>[] interfaces表示目标对象实现的一组接口。
InvocationHandler h表示当前的InvocationHandler实现实例对象。
实例:
package ProxyPattern_代理模式.DynamicProxy;
public interface Star {
/** 面谈 */
void confer();
/** 签合同 */
void signContract();
/** 订票 */
void bookTicket();
/** 唱歌 */
void sing();
/** 收尾款 */
void collectMoney();
}
package ProxyPattern_代理模式.DynamicProxy;
public class RealStar implements Star{
@Override
public void bookTicket() {
System.out.println("RealStar.bookTicket()");
}
@Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
}
@Override
public void confer() {
System.out.println("RealStar.confer()");
}
@Override
public void signContract() {
System.out.println("RealStar.signContract()");
}
@Override
public void sing() {
System.out.println("RealStar.sing()");
}
}
动态代理类:
实现
InvocationHandler
接口,并重写该invoke
方法。
package ProxyPattern_代理模式.DynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class StarHandler implements InvocationHandler
{
Star realStar;
public StarHandler(Star realStar) {
this.realStar = realStar;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj = null;
System.out.println("唱歌方法执行前:");
System.out.println("面谈--签合同--购票");
method.invoke(realStar, args);
System.out.println("唱歌方法执行后:");
System.out.println("收尾款");
return null;
}
}
客户端调用:
借助
Proxy.newProxyInstance
。
package ProxyPattern_代理模式.DynamicProxy;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
Star realStar = new RealStar();
StarHandler starHandler = new StarHandler(realStar);
//ClassLoader.getSystemClassLoader()
Star proxy = (Star) Proxy.newProxyInstance(realStar.getClass().getClassLoader(),new Class []{Star.class},starHandler);
proxy.sing();//其实是调的StarHandler类中重写的invoke()方法
}
}
使用Java动态代理机制的好处:
1、减少编程的工作量:假如需要实现多种代理处理逻辑,只要写多个代理处理器就可以了,无需每种方式都写一个代理类。
2、系统扩展性和维护性增强,程序修改起来也方便多了(一般只要改代理处理器类就行了)。