设计模式——代理模式

什么是代理

代理是指由委托方与代理方签订代理协议,授权代理方在一定范围内代表其向第三方进行商品买卖或处理有关事务。

代理模式

代理模式是面向对象编程中比较常见的设计模式。

 

1. 用户只关心接口功能,而不在乎谁提供了功能。上图中接口是 Subject。
2. 接口真正实现者是上图的 RealSubject,但是它不与用户直接接触,而是通过代理。
3. 代理就是上图中的 Proxy,由于它实现了 Subject 接口,所以它能够直接与用户接触。
4. 用户调用 Proxy 的时候,Proxy 内部调用了 RealSubject。所以,Proxy 是中介者,它可以增强 RealSubject 操作。

理解:Subject相当于酒类行业,RealSubject相当于酒类企业,比如茅台、五粮液等。用户去酒类企业授权的代理商那里买酒,而不是直接去企业那里买酒。代理商需要从企业进货。

 

静态代理

1. 定义一个Subject

package staticProxyDemo;

/**
 * Subject(主题)
 */
public interface SellWine {
    void maiJiu();
}

2. 定义一个RealSubject

package staticProxyDemo;

/**
 * RealSubject
 */
public class SellWuliangye implements SellWine {
    @Override
    public void maiJiu() {
        System.out.println("只见瓶身上写着:正宗五粮液,统一零售价,不卖九毛九,不卖九毛八,只卖一块九毛九!");
    }
}

3. 定义一个静态代理类

package staticProxyDemo;

/**
 * Proxy
 */
public class StaticProxy implements SellWine{
    private SellWine target;

    public StaticProxy(SellWine target){
        this.target=target;
    }

    @Override
    public void maiJiu() {
        System.out.println("代理商摆摊卖酒中……");
        System.out.println("有人来卖酒。");
        target.maiJiu();
        System.out.println("代理商把酒卖了出去。");
    }
}

4. 测试

package staticProxyDemo;

public class ProxyTest {
    public static void main(String[] args) {
        //主题是卖酒,卖的是五粮液
        SellWine sellWine =new SellWuliangye();
        //代理商获取卖酒的许可证
        StaticProxy staticProxy=new StaticProxy(sellWine);
        //代理商摆摊卖酒
        staticProxy.maiJiu();
    }
}

 运行结果:

 

动态代理

1.定义两个Subject

package dynamicProxyDemo;

/**
 * Subject1
 */
public interface SellSomething {
    void sell();
}

 

package dynamicProxyDemo;

/**
 * Subject2
 */
public interface BuySomething {
    void buy();
}

 

3. 定义对应的RealSubject

package dynamicProxyDemo;

public class SellWuliangye implements SellSomething {
    @Override
    public void sell() {
        System.out.println("只见招牌上写着:正宗五粮液,统一零售价,不卖九毛九,不卖九毛八,只卖一块九毛九!");
    }
}

 

package dynamicProxyDemo;

public class BuyAppliance implements BuySomething{
    @Override
    public void buy() {
        System.out.println("只听喇叭中喊着:回收彩电,冰箱,电视机,洗衣机!");
    }
}

 

4. 定义代理商创建类

package dynamicProxyDemo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态生成代理对象
 */
public class CreateProxy implements InvocationHandler {
    private Object target;//被代理的对象,如:Subject

    /**
     * 用于创建代理对象
     *
     * @return 代理对象
     */
    public Object proxy(Object target){
        this.target=target;
        //动态创建代理对象
        Object myProxy=Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
        return myProxy;
    }

    /**
     *
     * @param proxy 代理对象
     * @param method 被代理对象的方法
     * @param args   被代理对象的方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("-------------------------------------------------------");
        System.out.println("代理商在摆摊……");
        System.out.println("有人走了过来。");
        method.invoke(target,args);
        System.out.println("那人有走开了。");
        return null;
    }
}

5. 测试

package dynamicProxyDemo;

public class TestDynamicProxy {
    public static void main(String[] args) {
        //Subject是SellSomething、BuySomething
        //RealSubject是SellWuliangye、BuyAppliance
        SellSomething sellWuliangye = new SellWuliangye();
        BuySomething buyAppliance = new BuyAppliance();

        //创建代理商的工厂
        CreateProxy createProxy = new CreateProxy();
        //创建代理商1,并授予卖五粮液的许可证
        SellSomething proxy1 = (SellSomething) createProxy.proxy(sellWuliangye);//这里必须使用SellSomething,不能使用SellWuliangye
        proxy1.sell();//必须在创建proxy2之前调用,否则报错。
        //创建代理商2,并授予回收家电的经营证
        BuySomething proxy2 = (BuySomething) createProxy.proxy(buyAppliance);//这里必须使用SBuySomething,不能使用BuyAppliance
        proxy2.buy();
    }
}

 运行结果:

 

小结

1. 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。

 

2. 代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。

 

3. 代理类需要实现 Subject 接口,而静态代理中实现了Subject接口之后,当前代理类所要代理的类型就预定好了,如果有其他接口类型需要进行代理,就需要创建不同的代理类。同时,一旦接口增加方法,目标对象与代理对象都要维护,这些都很麻烦。所以有了动态代理。

 

4. 在动态代理中,我们可以让程序在运行的时候自动创建一个实现接口的代理对象,而不需要去定义一个预定好的代理类。这就是它被称为动态的原因。

 

个人理解: 静态代理就是我有几种产品需要进行销售,但产品种类不是很多,所以我直接选择不同的代理商进行代理销售。但随着产品种类地不断增多,为每种产品逐个找代理商比较麻烦,我想找一个大的代理平台进行统一销售,这就是动态代理。

 

参考链接

1. JAVA静态代理和动态代理理解

2. JAVA静态代、动态代理

posted @ 2021-09-12 10:44  云墨亦白  阅读(83)  评论(0)    收藏  举报