静态代理与动态代理

什么是代理模式

先介绍两个概念:通用业务核心业务

通用业务  指的是一些业务中,行为结果相同的子业务

核心业务  指的是一个业务中,特有的子业务,是其他业务没有的

    例子: A想吃饭得完成业务1:买菜——>做菜——>吃饭——>处理厨余垃圾

                B想吃饭得完成 业务2:买菜——>做菜——>吃饭——>处理厨余垃圾

业务1、业务2都可分为4个子业务,这四个子业务中买菜、做菜、处理厨余垃圾可以叫别人做(谁做结果都一样)、吃饭必须自己来(别人不能帮你把饭迟到你肚子里去),所以买菜、做菜、处理厨余垃圾就是通用业务,吃饭就是核心业务。

代理模式就是将通用业务交给代理类处理,其他委托类只负责自己的核心业务

代理模式实现如下:

客户想实现某个业务,直接调用接口的实现该业务的方法,实际是调用了代理类实现该业务的方法,代理类只实现通用业并调用委托类的对应方法实现核心业务。

优点:

  •     职责清晰:委托类只需专注实现自己的核心业务、不用理通用业务
  •     降低代码耦合
  •     扩展性强

静态代理模式实现代码

    背景:英雄都有Q、E技能,但英雄VN英雄GL的Q、E技能的实现各不相同,但他们都有前摇后摇

    1.定义一个英雄接口

public interface Hero {
	//Q技能
	public void Q();
	//E技能
	public void E();
}

    2.定义一个英雄VN类

public class VN implements Hero{
	@Override
	public void Q() {
		System.out.println("薇恩(Q技能):闪避突袭");
	}
	@Override
	public void E() {
		System.out.println("薇恩(E技能):恶魔审判");
	}
}

    3.定义一个英雄GL类

public class GL implements Hero{
	@Override
	public void Q() {
		System.out.println("盖伦(Q技能):致命打击");
	}
	@Override
	public void E() {
		System.out.println("盖伦(W技能):审判");
	}
}

    4.定义代理类

public class StaticProxy implements Hero{
	private Hero hero; //委托对象
	@Override
	public void Q() {
		System.out.println("技能前摇。。。");
		hero.Q();	//核心业务
		System.out.println("技能后摇。。。");
	}
	@Override
	public void E() {
		System.out.println("技能前摇。。。");
		hero.E();	//核心业务
		System.out.println("技能后摇。。。");
	}
	public void setHero(Hero hero) {
		this.hero = hero;
	}
}

    5.测试

	public static void main(String[] args) {
		StaticProxy proxy = new StaticProxy();
		proxy.setHero(new VN());//想调用VN的Q技能
		proxy.Q();
		System.out.println("==============");
		proxy.setHero(new GL());//想调用GL的Q技能
		proxy.Q();
	}

运行结果:

技能前摇。。。
薇恩(Q技能):闪避突袭
技能后摇。。。
==============
技能前摇。。。
盖伦(Q技能):致命打击
技能后摇。。。

 像技能前摇、技能后摇这些通用业务只需在代理类里实现,不必在每个英雄类中实现,降低代码耦合

动态代理模式实现代码

    英雄接口、VN类、GL类都和静态代理一样

    但还要定义个处理器类

public class ProxyHandle implements InvocationHandler{
    private Object target;//委托对象	
    /**
    * @param   proxy 代理对象
    * @param   method 接口对应的方法对象
    * @param   args 方法参数
    * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) 
            throws Throwable {
        System.out.println("技能前摇。。。");
        System.out.println(proxy.getClass());       //看看传入的对象是什么
        Object ret = method.invoke(target, args);	//核心业务
        System.out.println(method.getDeclaringClass());  //看看声明该方法的类是什么
        System.out.println("技能后摇。。。");
        return ret;
    }
    public Object getProxyInstance() throws NullTargetException {
    	if(target==null)
    		throw new NullTargetException("未设置委托对象");
        Class<?> clazz = target.getClass();
        //返回一个代理类对象,该代理类实现了target实现的接口
        return Proxy.newProxyInstance(
        		clazz.getClassLoader(), //类加载器
        		clazz.getInterfaces(),  //类实现的接口
        		this);                  //处理器
    }
	public void setTarget(Object target) {
		this.target = target;
	}
}

    测试代码

public static void main(String[] args) throws NullTargetException {
    ProxyHandle proxy = new ProxyHandle();
    proxy.setTarget(new VN());                     //设置委托对象
    Hero hero = (Hero)proxy.getProxyInstance();    //获得代理对象
    //实际调用了处理器的invoke方法,并把接口对应的方法对象和方法参数还有代理对象传入invoke方法
    hero.Q();
    System.out.println(hero.getClass());
    System.out.println("===========================");                                      
    proxy.setTarget(new GL());
    hero = (Hero)proxy.getProxyInstance();
    hero.Q();
    System.out.println(hero.getClass());
}

输出结果;

技能前摇。。。
class com.sun.proxy.$Proxy0
薇恩(Q技能):闪避突袭
interface com.mode.dynamic.Hero
技能后摇。。。
class com.sun.proxy.$Proxy0
===========================
技能前摇。。。
class com.sun.proxy.$Proxy1
盖伦(Q技能):致命打击
interface com.mode.dynamic.Hero
技能后摇。。。

Proxy.newProxyInstance方法主要是动态创建一个实现了委托对象的父接口代理类对象,代理类重写的方法都是调用处理器的invoke方法,并把代理类对象,方法对象(委托对象父接口声明的方法),方法参数(委托对象父接口声明的方法的参数)传入invoke方法

 

上面背景是英雄GL和VN都是英雄的、都只有Q、E技能情况,假设英雄GL既是英雄又是草丛三贱客而草丛三贱客特有蹲草丛的技能。下面是静态代理和动态代理的修改:

新增TreeCheapGuest接口

public interface ThreeCheapGuest {
	//蹲草丛
	public void stayInGrass();
}

GL类更改:

静态代理更改:

动态代理更改:

动态代理与静态代理相比:

    更大程度降低代码耦合

    无需编写代理类,扩展性更强

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值