设计模式-代理模式

1.代理模式概述

用一个类来代理另一个类的功能,为访问某个类的对象提供一种代理以控制访问。并且在此基础上增强原来的功能。
举例:

  • windows系统上的快捷方式,当我们需要运行一个软件时,不需要找到其安装位置双击.exe文件,而直接访问桌面上的快捷方式即可。
  • 火车站买票,我们不需要自己去火车站购买,可以去代售点购买,不过代价是收取一定的服务费。

在代理模式中有以下的几个角色:

  • 抽象主题角色:提供原始方法的接口
  • 真实主题角色:实现了的抽象主题角色的接口方法
  • 代理角色:同样实现了原始方法接口,并且聚合了真实主题角色。

接下来考虑这样一个场景,我们需要通过桌面快捷方式访问一个应用程序。那么分析之后可知,与上面角色一一对应,有以下的几个类和接口。

  1. Application:对应上面的抽象主题类,提供访问它的接口。
  2. ConcreteApplication:实现了访问应用程序的接口。
  3. ProxyApplication:代理角色

UML类图:
在这里插入图片描述

public interface Application {
    public void getRequest();
}


public class ConcreteApplication implements Application{
    @Override
    public void getRequest() {
        System.out.println("从磁盘路径xxxx中读取.exe文件----打开文件");
    }
}


public class ProxyApplication implements Application{
    private ConcreteApplication concreteApplication;

    public ProxyApplication(){
        concreteApplication=new ConcreteApplication();
    }
    @Override
    public void getRequest() {
        System.out.println("正在点击桌面快捷方式---正在重定向路径---");
        concreteApplication.getRequest();
    }
}
public class Client {
    public static void main(String[] args) {
        Application application=new ProxyApplication();
        application.getRequest();
        //
        正在点击桌面快捷方式---正在重定向路径---
        从磁盘路径xxxx中读取.exe文件----打开文件

    }
}

2.扩展

上述的写法被称为静态代理,在编译期间就已经确定。
实际上java语言为我们提供了另一种称为动态代理的模式,代理类对象的方法在运行时确定下来。

public class DynamicProxy {

    private ConcreteApplication concreteApplication=new ConcreteApplication();

    public Application getProxyObject(){

        ClassLoader loader = concreteApplication.getClass().getClassLoader();
        Class<?>[] interfaces = concreteApplication.getClass().getInterfaces();
        Object application=Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("正在点击桌面快捷方式---正在重定向路径");
                return method.invoke(concreteApplication, args);
            }
        });
        return (Application) application;
    }
}

实现原理是这样的:
底层会创建一个实现了Application接口的类,并且实现了getRequest()方法,而代理类的getRequest()方法中又调用了InvocationHandler重写的方法。
这种方法的好处是,当抽象代理角色中有很多的接口时,静态代理要求全部都实现,而动态代理则是根据需要动态完成。

cglib代替,上述情况是在有抽象主题类接口的情况下才能使用的。在没有接口的情况下,cglibjar包为我们提供了实现方法,继承现有的具体主题类。

public class CglibProxy implements MethodInterceptor {
    private ConcreteApplication concreteApplication=new ConcreteApplication();
    public ConcreteApplication getProxyObject(){
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(ConcreteApplication.class);
        enhancer.setCallback(this);
        ConcreteApplication object=(ConcreteApplication) enhancer.create();
        return object;

    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("正在点击桌面快捷方式---正在重定向路径---");
        Object invoke = method.invoke(concreteApplication, objects);
        return invoke;

    }
}

3.总结

注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

意图:为其他对象提供一种代理以控制对这个对象的访问。

主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

何时使用:想在访问一个类时做一些控制。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值