代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
介绍
意图:为其他对象提供一种代理以控制对这个对象的访问。

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

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

如何解决:增加中间层。

关键代码:实现与被代理类组合。

应用实例:
1、Windows 里面的快捷方式。
2、买火车票不一定在火车站买,也可以去代售点。
3、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。
4、spring aop。

优点: 1、职责清晰。 2、高扩展性。 3、智能化。

缺点:
1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

使用场景:按职责来划分,通常有以下使用场景:
1、远程代理。
2、虚拟代理。
3、Copy-on-Write 代理。
4、保护(Protect or Access)代理。
5、Cache代理。
6、防火墙(Firewall)代理。
7、同步化(Synchronization)代理。
8、智能引用(Smart Reference)代理。

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

实现
我们将创建一个 Image 接口和实现了 Image 接口的实体类。ProxyImage 是一个代理类,减少 RealImage 对象加载的内存占用。
ProxyPatternDemo,我们的演示类使用 ProxyImage 来获取要加载的 Image 对象,并按照需求进行显示。
代理模式的 UML 图
在这里插入图片描述
1.接口角色:定义所有需要被监听的行为
2.接口实现类
3.通知类
1)次要业务进行的具体实现
2)通知jvm,当前被拦截的主要业务方法与次要业务方法应该如何绑定执行
4.监控对象(代理对象)
1)被监控实例对象
2)需要被监控行为
3)具体通知类实例对象

静态代理

package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.staticProxy;

public interface Behavior {
    void eat();
}
package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.staticProxy;

public class ChineseBehaviorImpl implements Behavior {

    @Override
    public void eat() {
        System.out.println("中国人开始吃饭了");
    }
}
package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.staticProxy;

public class ChineseBehaviorProxyImpl implements Behavior {

    private Behavior behavior;//具体被监控的对象

    public ChineseBehaviorProxyImpl(Behavior behavior) {
        this.behavior = behavior;
    }

    @Override
    public void eat() {
        wash();
        behavior.eat();
    }
    public void wash() {
        System.out.println("洗手");
    }

    public static void main(String [] a){
        ChineseBehaviorImpl chineseBehaviorImpl =new ChineseBehaviorImpl();
        ChineseBehaviorProxyImpl ChineseBehaviorProxyImpl = new ChineseBehaviorProxyImpl(chineseBehaviorImpl);
        ChineseBehaviorProxyImpl.eat();
    }
}

动态代理

package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.jdk;

/**
 *
 */
public interface Behavior {

    void eat();
}
package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.jdk;

public class ChineseBehaviorImpl implements Behavior {

    @Override
    public void eat() {
        System.out.println("中国人开始吃饭了");
    }
}
package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 通知类
 */
public class Invaction implements InvocationHandler {

    private Behavior behavior;//具体被监控的对象

    public Invaction(Behavior behavior) {
        this.behavior = behavior;
    }

    /**
     * 在被监控的行为简要执行是会被jvm拦截
     * 被监控的行为和行为实现方会被作为参数给invoke
     * 通知jvm 这个拦截防范是如何与次要业务相结合的
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object o = null;
        if (method.getName().equals("eat")) {
            wash();
            o = method.invoke(behavior, args);
        }
        return o;
    }
    public void wash() {
        System.out.println("洗手");
    }
}
package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class ProxyFcatoryForJDK {

    /**
     * 代理对象的数据类型
     * 应该有监控行为来创建
     * 参数:class文件,监控类
     */
    public static Behavior builder(Class classFile) throws Exception {
        //1.创建被监控实例对象
        Behavior o = (Behavior)classFile.newInstance();
        //2.创建一个通知对象
        InvocationHandler adviser = new Invaction(o);
        /** 参数:被监控对象的类文件在内存中的地址
         *       被监控对象的类隶属文件的实现接口
         *       被监控的行为
         */
        Behavior  $proxy = (Behavior)Proxy.newProxyInstance(o.getClass().getClassLoader(),o.getClass().getInterfaces(),adviser);
        return $proxy;

    }
}
package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy;
import com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.cglib.ProxyCglibInvation;
import com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.cglib.Student;
import com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.jdk.Behavior;
import com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.jdk.ChineseBehaviorImpl;
import com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.jdk.ProxyFcatoryForJDK;

//吃饭前要洗手
public class ProxyMain {
    public static void main(String[] a) throws Exception {

        ProxyMain proxyMain = new ProxyMain();
        proxyMain.jdkProxy();
    }
    /**
     * 只能代理接口实现的类
     *
     * @throws Exception
     */
    public void jdkProxy() throws Exception {
        Behavior b = ProxyFcatoryForJDK.builder(ChineseBehaviorImpl.class);
        b.eat();
    }

Cglib实现代理模式

package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.cglib;
public class Student {

    public void say(){
        System.out.println("学习太难了");
    }
}

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class ProxyCglibInvation implements MethodInterceptor {


    @Override
    public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("老师让说");
        Object o = methodProxy.invokeSuper(obj, objects); //调用业务类(父类中)的方法
        return o;
    }
}
package com.example.javaex.javaex.DesignPatterns.ProxyPatterns.dynamicProxy.cglib;

import org.springframework.cglib.proxy.Enhancer;

public class ProxyFcatoryForCglib {


    private Object target;//业务类对象,供代理方法中进行真正的业务方法调用
    private ProxyCglibInvation proxyCglibInvation;

    public ProxyFcatoryForCglib(Object target, ProxyCglibInvation proxyCglibInvation) {
        this.target = target;
        this.proxyCglibInvation = proxyCglibInvation;
    }

    //相当于JDK动态代理中的绑定
    public Object bulid() {
        Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
        enhancer.setSuperclass(this.target.getClass());  //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(proxyCglibInvation);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }
}

PS:部分内容来自菜鸟教程代理模式
http://www.runoob.com/design-pattern/proxy-pattern.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值