掘金 阅读 ( ) • 2021-06-20 23:31
.markdown-body{word-break:break-word;line-height:1.75;font-weight:400;font-size:15px;overflow-x:hidden;color:#333}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{line-height:1.5;margin-top:35px;margin-bottom:10px;padding-bottom:5px}.markdown-body h1{font-size:30px;margin-bottom:5px}.markdown-body h2{padding-bottom:12px;font-size:24px;border-bottom:1px solid #ececec}.markdown-body h3{font-size:18px;padding-bottom:0}.markdown-body h4{font-size:16px}.markdown-body h5{font-size:15px}.markdown-body h6{margin-top:5px}.markdown-body p{line-height:inherit;margin-top:22px;margin-bottom:22px}.markdown-body img{max-width:100%}.markdown-body hr{border:none;border-top:1px solid #ddd;margin-top:32px;margin-bottom:32px}.markdown-body code{word-break:break-word;border-radius:2px;overflow-x:auto;background-color:#fff5f5;color:#ff502c;font-size:.87em;padding:.065em .4em}.markdown-body code,.markdown-body pre{font-family:Menlo,Monaco,Consolas,Courier New,monospace}.markdown-body pre{overflow:auto;position:relative;line-height:1.75}.markdown-body pre>code{font-size:12px;padding:15px 12px;margin:0;word-break:normal;display:block;overflow-x:auto;color:#333;background:#f8f8f8}.markdown-body a{text-decoration:none;color:#0269c8;border-bottom:1px solid #d1e9ff}.markdown-body a:active,.markdown-body a:hover{color:#275b8c}.markdown-body table{display:inline-block!important;font-size:12px;width:auto;max-width:100%;overflow:auto;border:1px solid #f6f6f6}.markdown-body thead{background:#f6f6f6;color:#000;text-align:left}.markdown-body tr:nth-child(2n){background-color:#fcfcfc}.markdown-body td,.markdown-body th{padding:12px 7px;line-height:24px}.markdown-body td{min-width:120px}.markdown-body blockquote{color:#666;padding:1px 23px;margin:22px 0;border-left:4px solid #cbcbcb;background-color:#f8f8f8}.markdown-body blockquote:after{display:block;content:""}.markdown-body blockquote>p{margin:10px 0}.markdown-body ol,.markdown-body ul{padding-left:28px}.markdown-body ol li,.markdown-body ul li{margin-bottom:0;list-style:inherit}.markdown-body ol li .task-list-item,.markdown-body ul li .task-list-item{list-style:none}.markdown-body ol li .task-list-item ol,.markdown-body ol li .task-list-item ul,.markdown-body ul li .task-list-item ol,.markdown-body ul li .task-list-item ul{margin-top:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:3px}.markdown-body ol li{padding-left:6px}.markdown-body .contains-task-list{padding-left:0}.markdown-body .task-list-item{list-style:none}@media (max-width:720px){.markdown-body h1{font-size:24px}.markdown-body h2{font-size:20px}.markdown-body h3{font-size:18px}}

这是我参与更文挑战的第18天,活动详情查看:更文挑战

代理模式

代理模式也称之为委托模式。当一个对象不能直接访问另一个对象的时候需要找一个中间对象帮忙处理这件事情,这个中间对象就是代理对象了。

代理模式的定义:给对象类提供一个代理以控制该对象的访问。访问对象不适合或不能直接访问目标对象,代理对象作为访问对象和目标对象的中介。

静态代理

代理模式包含三个角色:抽象主题类、真实主题类、代理类。代理类和真实主题类都是对抽象主题类的具体实现。但对于客户端来讲,真实主题类是无法直接使用请求的,需要通过代理类间接使用。Proxy构造函数入参对象是抽象主题类,在实际情况将真实主题类做为Proxy构造函数的入参对象,然后调用Proxy的方法并能间接调用到RealSubject真正要执行的方法了。

//抽象主题
interface Subject {
    void Request();
}
//真实主题
class RealSubject implements Subject {
    public void Request() {
        // 执行
    }
}
//代理
class Proxy implements Subject {
    private RealSubject realSubject;
    
    public Proxy(Subject subject){
        this.subject = subject;
    }
    public void Request() {
        preRequest();
        realSubject.Request();
        postRequest();
    }
    public void preRequest() {
      // 请求前
    }
    public void postRequest() {
      // 请求后
    }
}
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.Request();
复制代码

动态代理

上述代码中描述的是代理模式静态代理。代理其实是分为两大部分:静态代理和动态代理。静态代理就是由开发者自行编写代理对象实现。而动态代理则是通过反射机制动态地生成代理者对象,代理只有在运行时才知道代理的对象是谁。

如下代码可见动态代理可以通过一个代理类来代理N多个被代理类,其实本质上是对代理者和被代理者的解耦。

public class DynamicProxy implements InvocationHandler{

    private Object obj;
    
    public DynamicProxy(Object obj){
        this.obj = obj;
    }

    @override
    public Object invoke(Object arg,Method arg1,Object[] arg2) throws Throwable{
        Object result = method.invoke(obj,args);
        return result;
    }
}

RealSubject realSubject = new RealSubject();

DynamicProxy dynamicProxy = new DynamicProxy(realSubject);
ClassLoader loader = realSubject.getClass().getClassLoader();

Subject subject = (Subject) Proxy.newProxyInstance(loader,new Class[]{Subject.class},proxy);
subject.Request();

复制代码

总结

代理模式应用还是比较广泛。对于代理模式中使用静态代理还是动态代理具体还是需要看开发者自己的偏向。静态代理而言只能为给定接口的实现类做代理,后期若接口发生改变就需要重新定义代理类,较为繁琐。动态代理更加灵活方便,对于被代理对象是一对多的关系在使用上来讲确实便捷。