设计模式

[码歌老薛]动态代理之多级代理实现方案以及细节分析

2018-12-19  本文已影响62人  坑王老薛

本内容均属码歌老薛原创,需要转载请注明出处:https://www.jianshu.com/p/29548a7b606f
对于本文章如果有疑问,请加老薛qq:1811112688

1-7-6 多级代理

业务分析

实现业务场景:虾米吃海藻 小鱼吃虾米,大鱼吃小鱼

简单业务概述,当虾米吃海草时,小鱼一直在监视虾米有没有执行eat();方法,如果执行则小鱼执行eatSmallShrimp();大鱼执行eatLitteFish();将小鱼吃掉。

1-7-6 需求分析第一步
i:主要业务和次要业务的分析,这里吃为主要业务,当虾米吃了海藻,意味着小鱼一直在监听虾米吃的动作,如果虾米吃的动作一旦完成,或者被调用,意味着小鱼就要准备出场,将虾米干掉。
ii:根据上面的分析也就意味着小鱼应该是一个Agent对象,里面存储了次要业务,吃小虾米。
1-7-7 编写方式

1: 创建主要业务接口

2:创建虾米对象且实现主要业务接口

3:创建实现处理器类

4:编写代理工厂,代理对象通过工厂创建出来

5:编写测试类

1-7-8 测试用例
主要业务接口
/**
 * 编写主要核心业务逻辑
 */
public interface Service {
    void eat();
}
虾米类实现主要业务接口
public class SmallShrimp implements Service {
    @Override
    public void eat() {
        System.out.println("虾米吃海藻");
    }
}
代理工厂
public class ProxyFactory {

    public static Service getInstance(Class<?> clz){

        //创建真实角色
        SmallShrimp shrimp = new SmallShrimp();

        //获取代理角色 (实现了处理器接口的对象)
        LittleFish fish = new LittleFish(shrimp);

        //获取监听对象,查看真实角色是否执行了主要业务
        Class[] clzArrays = {Service.class};
        Service proxy = (Service) Proxy.newProxyInstance(clz.getClassLoader(),clzArrays,fish);
       
        return proxy;
    }
}
创建实现处理器类
public class LittleFish implements InvocationHandler {

    //包装真实角色
    private Service realObj;

    public LittleFish(Service realObj) {
        this.realObj = realObj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //监听虾米是否开始吃海藻了
        method.invoke(realObj,args);

        //准备让小鱼吃虾米
        eatSS();
        return null;
    }

    public void eatSS(){
        System.out.println("小鱼准备吃虾米");
    }
}
测试类
public class Test {
    public static void main(String[] args) throws Exception {
        Service service =  ProxyFactory.getInstance(SmallShrimp.class);

        service.eat();

    }
}
结论
虾米吃海藻
小鱼准备吃虾米
1-7-9 需求分析第二步
i: 分析大鱼小鱼的业务场景,大鱼在监控小鱼,如果发现小鱼吃了虾米,
那么此时大鱼开始执行它吃小鱼的功能。这里有一个问题需要我们解决,
对于小鱼来说,它的主要业务好像应该是吃小鱼的方法eatSS();
这里要注意:
ii:因为整个业务场景中,其实是虾米吃海藻发生之后,
代理角色才被创建以及开始执行的。
1-7-7 编写方式

1:创建实现处理器类 代理实现类,大鱼类

4:编写代理工厂,代理对象通过工厂创建出来

5:编写测试类

1-7-8 编写方式
主要业务接口
/**
 * 编写主要核心业务逻辑
 */
public interface Service {
    void eat();
}
虾米类实现主要业务接口
public class SmallShrimp implements Service {
    @Override
    public void eat() {
        System.out.println("虾米吃海藻");
    }
}
代理工厂
public class ProxyFactory {

    public static Service getInstance(Class<?> clz){

        //创建真实角色
        Service shrimp = new SmallShrimp();

        //获取代理角色 (实现了处理器接口的对象)
        InvocationHandler fish = new LittleFish(shrimp);

        //获取监听对象,查看真实角色是否执行了主要业务
        Class[] clzArrays = {Service.class};
        Service proxy1 = (Service) Proxy.newProxyInstance(clz.getClassLoader(),clzArrays,fish);

        //创建代理实现类对象
        InvocationHandler bigFish = new BigFish(proxy1);
        //这里获取监听对象 查看小鱼是否执行了吃虾米的操作,但是整个业务流程其实都是起始于小鱼除了虾米 所以这里负责
        //查看的依旧是小鱼
        Service proxy2 = (Service) Proxy.newProxyInstance(clz.getClassLoader(),clzArrays,bigFish);

        return proxy2;
    }
}

创建实现处理器类1
public class LittleFish implements InvocationHandler {

    //包装真实角色
    private Service realObj;

    public LittleFish(Service realObj) {
        this.realObj = realObj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //监听虾米是否开始吃海藻了
        method.invoke(realObj,args);

        //准备让小鱼吃虾米
        eatSS();
        return null;
    }

    public void eatSS(){
        System.out.println("小鱼准备吃虾米");
    }
}
创建实现处理器类2
public class BigFish implements InvocationHandler {

    private Service proxy;

    public BigFish(Service proxy) {
        this.proxy = proxy;
    }

    @Override
    public Object invoke(Object listener, Method method, Object[] args) throws Throwable {
        /**
         * 监听小鱼有没有吃虾米 如果吃了则准备吃小鱼 这里的问题是真实的执行对象是谁?
         * 按照我们思路应该是小鱼,但是小鱼执行的是invoke方法,而该方法其实是通过监控执行的,而不是
         * 主动调用的,这个方法的调用是由产生的代理对象执行的,所以这里我们执行该方法的对象应该是Proxy,
         * 所以对于BigFish而言需要一个Proxy的引用
         */
        method.invoke(proxy,args);
        eatLF();
        return null;
    }
    //辅助业务
    public void eatLF(){
        System.out.println("大鱼吃小鱼");
    }
}

测试类
public class Test {
    public static void main(String[] args) throws Exception {
        Service service =  ProxyFactory.getInstance(SmallShrimp.class);

        service.eat();

    }
}
结论
虾米吃海藻
小鱼准备吃虾米
大鱼吃小鱼
上一篇下一篇

猜你喜欢

热点阅读