设计模式--代理模式

来源:互联网 发布:64位 mysql 编辑:程序博客网 时间:2024/06/17 11:05

代理模式(Proxy Pattern)

两个对象参与处理同一个请求,接收的请求由代理对象委托给真实对象处理,代理对象控制请求的访问,它在客户端应用程序与真实目标对象之间起到一个中介桥梁的作用。大类上划分为结构型模式。
代理模式中有三种角色,1. 抽象角色,声明真实对象和代理对象的共同接口。2. 真实角色:真正处理请求的目标对象。3. 代理角色,代理角色内部含有真实对象的引用,从而代理代理对象可以将请求转交给真实对象处理。同时,代理对象在执行真实对象操作的前后还可以添加附加操作(Spring的AOP)。
代理角色可以在处理请求中,做一些初步的判断,校验等非业务工作(这些操作可以减少真实对象的压力,也保护真实对象),等到需要执行真正业务逻辑的时候则调用真实对象进行操作。
代理模式,常用静态代理和动态代理。
静态代理比较简单,定义一个接口,用来声明真实角色和代理角色的共同操作;一个代理类(包含真实对象的引用,真实对象相同的操作方法);真实对象类,执行具体的操作。例如红酒接口(抽象角色,生产,销售)。红酒代理商类(代理角色,生产,销售)。红酒工厂(真实角色,生产,销售)。
动态代理,所谓动态代理,就是一个系统在没有统一接口的情况下,在运行时,动态地对那些接口不同的对象提供代理支持。在JAVA中动态代理的核心是java.lang.reflect.InvocationHandler接口,要使用动态代理则必须实现该接口,这个接口的委派任务是在invoke(Object proxy, Method m, Object[] args)方法里实现的。

介绍

意图:为其他对象提供一种代理以控制这个对象的访问。
使用场景:1. 远程代理,为一个对象在不同的地址空间提供局部代理。2. 虚拟代理,若一个对象的创建非常耗时,可通过代理对象去调用,在真实对象创建前,返回一个假的调用,等真实对象创建好了,这是返回给客户的就是一个真实对象的相应方法调用。3. 保护代理,控制对原始对象的访问。
优点:1. 职责清晰。2. 高扩展性。3. 智能化。
缺点:1. 由于在客户端和真实对象之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。2. 实现代理模式需要额外的工作,个别代理的实现非常复杂。
注意事项:1. 和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。2. 和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

实现

静态代理

静态代理实现模拟一个红酒工厂,和红酒代理商的代理关系。

步骤 1

我们创建一个红酒接口(抽象角色)。
IRedWine.java

package com.study.Proxy;public interface IRedWine {    /**     * 生产红酒     */    void product();    /**     * 销售红酒     */    void sell();}

步骤 2

创建一个红酒工厂类(真实角色),该类实现了红酒接口。
RedWineFactory.java

package com.study.Proxy;public class RedWineFactory implements IRedWine{    public void product() {        System.out.println("红酒工厂生产中。。。");    }    public void sell() {        System.out.println("红酒工厂红酒售卖中。。。");    }}

步骤 3

创建一个红酒销售商(代理角色,代理红酒工厂),该类实现了红酒接口。
RedWineSellerProxy.java

package com.study.Proxy;public class RedWineSellerProxy implements IRedWine{    /**     * 代理角色中对真实角色的引用     */    private final IRedWine redWine;    public RedWineSellerProxy(IRedWine wine) {        this.redWine = wine;    }    public void product() {        System.out.println("使用代理角色进行红酒生产:");        System.out.println("当然也可以做其他的事:");        redWine.product();    }    public void sell() {        System.out.println("使用代理角色进行红酒销售:");        System.out.println("当然也可以做其他的事:");        redWine.sell();    }}

步骤 4

测试验证,采用main方法实现。
TestProxy.java

package com.study.Proxy;public class TestProxy {    public static void main(String[] args) {        IRedWine wineFactory = new RedWineFactory();        IRedWine sellProxy = new RedWineSellerProxy(wineFactory);        sellProxy.product();        sellProxy.sell();    }}

验证输出。

使用代理角色进行红酒生产:当然也可以做其他的事:红酒工厂生产中。。。使用代理角色进行红酒销售:当然也可以做其他的事:红酒工厂红酒售卖中。。。

动态代理

步骤 1

创建代理接口。
ITarget.java

package com.study.Proxy;public interface ITarget {    /**     * 操作方法     */    void operation();}

步骤 2

创建实际操作对象,实现了InvocationHandler接口。
TargetImpl.java

package com.study.Proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class TargetImpl implements InvocationHandler{    @override    public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {        System.out.println("执行的方法名字:" + arg1.getName());        System.out.println("实现动态代理!!!");        return null;    }}

步骤 3

创建测试类。
DynamicClient.java

package com.study.Proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class DynamicClient {    public static void main(String[] args) {        //真实处理对象        InvocationHandler handler = new TargetImpl();        //创建代理类实例对象        ITarget target = (ITarget) Proxy.newProxyInstance(ITarget.class.getClassLoader(),                 new Class[] {ITarget.class}, handler);        target.operation();    }}

验证输出。

执行的方法名字:operation实现动态代理!!!
0 0