美文网首页
代理模式

代理模式

作者: 叶小然 | 来源:发表于2019-06-26 18:38 被阅读0次

代理模式分为静态代理和动态代理。动和静的主要区别,在于是否提前知道代理的类型。就像我们说多态的动态绑定一样,动态绑定是指运行时绑定,在编写代码时不关心具体类型。

这次的场景是咖啡店,根据不同的场景提供静态代理和动态代理的解决方案。

静态代理

咖啡店是接口,只有一个方法make,星巴克和瑞幸两个门店各自实现了自己的make。
场景1:瑞幸在推大师咖啡,但是初期大师没到位,只能先做“贴牌”,从星巴克点个咖啡,换成自己的小蓝杯,再给顾客送过去。虽然是不合法,但是这种模式就叫静态代理。

/**
 * 咖啡店接口
 * @author yeziran
 */
public interface CoffeeStore {
    
    /**
     * 咖啡制作
     */
    public void make();
}

2个实现类:

/**
 * 星巴克咖啡
 * @author yeziran
 *
 */
public class Starbuck implements CoffeeStore {
    @Override
    public void make() {
        System.out.println("星巴克咖啡制作中...");
        System.out.println("星巴克咖啡制作完成");
    }
}
/**
 * 静态代理,A和B实现同一接口,B的构造器注入A,B的接口实现调用A的实现
 * @author yeziran
 *
 */
public class Luckin implements CoffeeStore {
    
    private CoffeeStore cStore;
    
    public Luckin(CoffeeStore cStore) {
        this.cStore = cStore;
    }

    @Override
    public void make() {
        System.out.println("瑞幸大师咖啡制作中...");
        System.out.println("瑞幸大师赶紧在"+cStore.getClass().getSimpleName()+"点了一份咖啡");
        cStore.make();
        System.out.println("瑞星大师咖啡制作完成");
    }
}

main方法模拟消费者:

public class CoffeeCustomer {
    public static void main(String[] args) {
        CoffeeStore starbuck = new Starbuck();
        CoffeeStore luckin = new Luckin(starbuck);
        starbuck.make();
        System.out.println();
        luckin.make();
    }
}

运行得到输出:

星巴克咖啡制作中...
星巴克咖啡制作完成

瑞幸大师咖啡制作中...
瑞幸大师赶紧在Starbuck点了一份咖啡
星巴克咖啡制作中...
星巴克咖啡制作完成
瑞星大师咖啡制作完成

动态代理

场景2:美团外卖代理了2种咖啡,客户可以在美团客户端同时点2种咖啡,并且同时星巴克可以支持点食品。那么,美团就不能是通过注入一个咖啡店类型的静态代理类了,因为它还得卖食品,所以在编写代码时还不能确定被代理的类型,那么就需要动态代理来提供解决方案。

增加一个食品接口

/**
 * 食品站
 * @author yeziran
 */
public interface FoodStation {
    
    public void cook();
}

对星巴克咖啡店的改造,实现FoodStation接口,使它具备制作食品的能力:

/**
 * 星巴克咖啡
 * @author yeziran
 *
 */
public class Starbuck implements CoffeeStore, FoodStation {

    @Override
    public void make() {
        System.out.println("星巴克咖啡制作中...");
        System.out.println("星巴克咖啡制作完成");

    }

    @Override
    public void cook() {
        System.out.println("星巴克火腿卷面包制作中...");
        System.out.println("星巴克火腿卷面包制作完成");
        
    }

}

实现动态代理,必须实现接口InvocationHandler,那么美团的类型就变成这样:

/**
 * 美团外卖
 * <br>
 * 动态代理,通过实现InvocationHandler接口,利用反射的Method.invoke方法调用目标实现
 * 
 * @author yeziran
 *
 */
public class Meituan implements InvocationHandler {
    
    private Object target;
    
    public Meituan(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("美团外卖开始接单...");
        System.out.println("美团外卖新订单,预定外卖为 " + target.getClass().getSimpleName());
        method.invoke(target, args);
        System.out.println("美团外卖配送中...");
        System.out.println("美团外卖订单结束。");
        System.out.println();
        return null;
    }
}

客户端调用的时候,需要主动地使用Proxy.newProxyInstance方式创建一个被代理的实例,这样在调用对应方法的时候,InvocationHandler的invoke接口会被调用到,也就是上面重写的invoke方法。

public class CoffeeCustomer {
    
    
    public static void main(String[] args) {
        CoffeeStore starbuck = new Starbuck();
        CoffeeStore luckin = new Luckin(starbuck);
        
        InvocationHandler meituan = new Meituan(luckin);//瑞幸实例
        CoffeeStore dProxy = (CoffeeStore) Proxy.newProxyInstance(luckin.getClass().getClassLoader(), 
                luckin.getClass().getInterfaces(), meituan);
        dProxy.make();
        meituan = new Meituan(starbuck);//星巴克实例
        CoffeeStore dProxy2 = (CoffeeStore) Proxy.newProxyInstance(starbuck.getClass().getClassLoader(), 
                starbuck.getClass().getInterfaces(), meituan);
        dProxy2.make();
        FoodStation dProxy3 = (FoodStation) Proxy.newProxyInstance(starbuck.getClass().getClassLoader(), 
                starbuck.getClass().getInterfaces(), meituan);
        dProxy3.cook();
            
        dProxy.make();
        dProxy2.make();
        dProxy3.cook();
    }
}

得到输出:

美团外卖开始接单...
美团外卖新订单,预定外卖为 Luckin
瑞幸大师咖啡制作中...
瑞幸大师赶紧在Starbuck点了一份咖啡
星巴克咖啡制作中...
星巴克咖啡制作完成
瑞星大师咖啡制作完成
美团外卖配送中...
美团外卖订单结束。

美团外卖开始接单...
美团外卖新订单,预定外卖为 Starbuck
星巴克咖啡制作中...
星巴克咖啡制作完成
美团外卖配送中...
美团外卖订单结束。

美团外卖开始接单...
美团外卖新订单,预定外卖为 Starbuck
星巴克火腿卷面包制作中...
星巴克火腿卷面包制作完成
美团外卖配送中...
美团外卖订单结束。

美团外卖开始接单...
美团外卖新订单,预定外卖为 Luckin
瑞幸大师咖啡制作中...
瑞幸大师赶紧在Starbuck点了一份咖啡
星巴克咖啡制作中...
星巴克咖啡制作完成
瑞星大师咖啡制作完成
美团外卖配送中...
美团外卖订单结束。

美团外卖开始接单...
美团外卖新订单,预定外卖为 Starbuck
星巴克咖啡制作中...
星巴克咖啡制作完成
美团外卖配送中...
美团外卖订单结束。

美团外卖开始接单...
美团外卖新订单,预定外卖为 Starbuck
星巴克火腿卷面包制作中...
星巴克火腿卷面包制作完成
美团外卖配送中...
美团外卖订单结束。

相关文章

  • 设计模式

    单例模式 模板方法模式 工厂模式 代理模式 静态代理 JDK动态代理

  • 设计模式

    单例模式 代理模式 静态代理 jdk动态代理 cglib动态代理 工厂模式 适配器模式 建造者模式 观察者模式

  • kube-proxy的3种模式

    userspace代理模式 iptables代理模式 IPVS代理模式 https://kubernetes.io...

  • 第4章 结构型模式-代理模式

    一、代理模式简介 二、代理模式3个角色 三、代理模式的优点 四、代理模式的实例(游戏代练)

  • 理解代理模式

    原创博客地址 简介 代理模式,也叫做委托模式,分为:静态代理动态代理 代理模式也是平时比较常用的设计模式之一,代理...

  • 结构型 代理模式(文末有项目连接)

    1:什么是代理模式 2:没用代理模式时的实例 3:使用代理模式将其解耦(静态代理) 3:使用代理模式将其解耦(动态...

  • 设计模式-动态代理模式

    之前介绍了代理模式,大家也都了解了代理模式,不过之前介绍的代理模式是静态代理,静态代理什么意思?静态代理指的是代理...

  • 代理模式

    一、什么是代理模式 代理模式(Proxy pattern):代理模式又叫委托模式,是为某个对象提供一个代理对象,并...

  • 设计模式之代理模式(Proxy模式)

    代理模式的引入 代理模式的实例程序 代理模式的分析 代理模式的引入 Proxy是代理人的意思,指的是代替别人进行工...

  • Java设计模式之代理模式

    Java设计模式之代理模式 代理模式 静态代理 动态代理 为什么需要代理 通过代理,我们能够不用知道委托人是谁,而...

网友评论

      本文标题:代理模式

      本文链接:https://www.haomeiwen.com/subject/beaccctx.html