设计模式--代理模式

代理模式(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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值