设计模式详解(八)——代理模式

代理模式简介

代理模式定义
代理模式是 Java 常见的设计模式之一。代理模式就是在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理对象,来间接的调用实际的对象。通俗的来讲代理模式就是我们生活中常见的中介。当我们使用代理对象来代替对真实对象的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
通俗点举个例子解释:当我们要访问一些国外的网站时,就发现访问不了,这个时候就会需要用到VPN,他可以帮助我们去访问一些国内不能访问的网站,也就是说他代理了这个访问过程,把结果返回给了我们。这就是代理模式。

代理模式包含以下角色:

  1. 客户端:客户端访问代理者与访问被代理者具有类似的效果,其无法区分访问的是代理者还是被代理者。
  2. 抽象主题:一般实现为接口,是对被代理对象的行为的抽象。其主要职责是声明真实主题与代理的共同接口方法。
  3. 被代理角色(目标类):直接实现上述接口,是抽象主题的具体实现。该类定义了代理所表示的真实对象,是负责执行系统真正的逻辑业务对象
  4. 代理角色(代理类):实现上述接口,是对被代理角色的增强

代理模式优缺点:
优点:
1、代理模式能将代理对象与真实被调用的目标对象分离。
2、一定程度上降低了系统的耦合度,扩展性好。
3、可以起到保护目标对象的作用。
4、可以对目标对象的功能增强
5、在不修改目标对象的功能前提下,能通过代理对象对目标进行拓展

缺点:
1、代理模式会造成系统设计中类的数量增加。
2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
3、增加了系统的复杂度。
4、因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,增加了不必要的开发成本。

使用场景
(1)系统需要使用现有的类,而此类的接口不符合需要。
(2)需要一个统一的输出接口,而输入类型不可预知。
(3)创建一个可以复用的类,使得该类可以与其他不相关的类或不可预见的类(协同工作。

代理模式的实现
代理模式有两种:静态代理和动态代理。
静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类
应用实例
动态代理代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理;代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象;动态代理也叫做:JDK代理、接口代理

静态代理和动态代理的区别
静态代理只能通过手动完成代理操作,如果被代理类增加新方法,代理类需要同步新增方法,违背开闭原则
动态代理采用运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则
若动态代理需要对目标类的增强逻辑扩展,结合策略模式,只需新增策略类便可完成,无需修改代理类代码

以下举一个代理模式的例子:
例如:VPN

先实现一个抽象主题,用来处理请求

/**
 * @author yyx
 */
public interface Request {
    // 处理请求
    void processRequest();
}

然后写一个可以访问YouKu实现类:

/**
 * @author yyx
 */
public class Youku implements Request {
    @Override
    public void processRequest() {
        System.out.println("你正在访问优酷");
    }
}

写一个测试类,用于用户访问YouKu

/**
 * @author yyx
 */
public class Client {
    public static void main(String[] args) {
        Request request = new Youku();
        request.processRequest();
    }
}

输出结果如下所示:

你正在访问优酷

然后写一个不可以正常访问Youtube 实现类:

/**
 * @author yyx
 */
public class Youtube implements Request {
    @Override
    public void processRequest() {
        System.out.println("你正在访问youtube.....");
    }
}

因为国内无法正常登录Youtube ,就需要一个VPN代理类帮我们访问。并且这个VPN会有一些其他操作。

你要先登录VPN,然后连接才能访问,最后要关掉VPN

/**
 * @author yyx
 */
public class VPN implements Request{
    private Request request;
    public VPN() {
    }
    public void setRequest(Request request) {
        login();
        lianJie();
        this.request = request;
        close();
    }
    @Override
    public void processRequest() {
        request.processRequest();
    }
    private void login() {
        System.out.println("登录VPN");
    }
    private void lianJie() {
        System.out.println("VPN连接");
    }
    private void close() {
        System.out.println("关闭VPN");
    }
}

写一个测试类,用于用户访问Youtube

/**
 * @author yyx
 */
public class Client {
    public static void main(String[] args) {
        Request request = new Youtube();
        VPN vpn = new VPN();
        vpn.setRequest(request);
        vpn.processRequest();
    }
}

输出结果如下所示:

登录VPN
VPN连接
你正在访问youtube.....
关闭VPN

总而言之:
设计模式就是帮助我们开发的,因此我们需要在使用的过程中根据真实情况去选择静态代理还是动态代理,是使用cglib还是jdk。代理模式应用广泛,而且代理模式几乎没有缺点可言,它是细分化至很小的一种模式。
而且代理模式是比较常见的模式,除了上面介绍的智能指针,它还广泛用于网络应用开发,比如远程代理服务器等。当我们想控制一个对象的访问时,可以使用代理模式把客户代码和实际对象隔离开来,提供一个中间层来管理对实际对象的访问,把客户和对象解耦合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值