大话设计模式(总结)--代理模式

代理模式

--什么是代理模式?

为其他对象提供一种代理,以控制这个对象的访问。说白了就是,在一些情况下,客户不想或者不能直接引用一个对象。而代理对象可以在客户和目标之间起到中介作用,去掉客户不能看到的内容和服务或者增加客户需要的额外服务。

--代理模式使用场景?

在对已有的方法进行使用的时候出现需要对原有方法进行修改,这时候:有两种选择。1.修改原有方法 2.使用一个第三者方法来调用原有的方法,并且对方法的产生的结果进行一定的控制。第一种明显违背了,对扩展开发,对修改关闭(开闭原则),而且在原来方法中修改可能使得原来类的功能变得模糊和多元化(就像现在企业多元化一样),而使用第二种方式,可以将功能划分的更加清晰,有助于后面的维护。所以在一定程度上,第二种方式是一个比较好的选择。当然,如果系统小的话,完全不用层层代理。反而显得臃肿。

--代理模式类比?

网上售票点 --黄牛 --你

你通过黄牛(代理角色)买票。黄牛其实也是在网上售票点(真实角色)买的票。黄牛作为代理角色,不仅会卖电影票,还会卖其他旅游景点的票。实现了增强。

--代理模式的角色?

抽象角色(Subject):声明真实对象和代理对象的共同接口;

代理角色(ProxySubject):代理角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象,相同的接口。以便任何时刻,都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他操作,相当于对于真实对象进行封装

真实角色(RealSubject):代理角色所代表的真实对象,是我们最终引用的对象

大话设计模式(总结)--代理模式_第1张图片

代理模式分类

--静态代理

静态代理就是程序运行前就已经存在的代理类字节码文件,代理类和委托类关系在运行前就确定了。

/**
 * 抽象角色,真实对象和代理对象的接口
 *
 * @author LiJie
 * @create 2018/1/18 16:39
 */
public interface Subject {
    /**
     * 让我们来做些事
     */
    void doSomeThing();
}

/**
 * 真实角色:代理角色所代表的真实对象
 *
 * @author LiJie
 * @create 2018/1/18 16:42
 */
public class RealSubject implements Subject {
    @Override
    public void doSomeThing() {
        System.out.println("我是真实角色");
    }
}

/**
 * 代理角色:替真实角色出头的
 *
 * @author LiJie
 * @create 2018/1/18 16:40
 */
public class ProxySubject implements Subject {
    //目标对象引用
    private Subject subject;
    public ProxySubject(Subject subject) {
        this.subject = subject;
    }
    @Override
    public void doSomeThing() {
        System.out.println("我是代理角色");
        subject.doSomeThing();
    }

    /**
     * 除了代理真实角色,做事。还可以做些私活
     */
    public void doAnotherThing() {
        System.out.println("我是代理角色,还可以挣些外快");
    }
}

/**
 * 测试类
 *
 * @author LiJie
 * @create 2018/1/18 16:49
 */
public class TestSubject {

    public static void main(String []args) {
        //真实角色引用
        Subject subject = new RealSubject();
        ProxySubject proxySubject = new ProxySubject(subject);
        proxySubject.doSomeThing();
        //封装真实角色,扩展方法。
        proxySubject.doAnotherThing();
    }
}

--动态代理

动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。

Proxy.newProxyIntance().方法说明。

参数1:类加载器(这个参数可去掉)

参数2:代理的接口(可以选择性代理接口)

参数3:InvocationHandler的实现类。该接口解开类与拦截类之间的耦合

/**
 * 代理工厂类
 *
 * @author LiJie
 * @create 2018/1/18 17:16
 */
public class ProxyFactory {
    //维护一个目标对象
    private Object subject;
    public ProxyFactory(Object subject) {
        this.subject = subject;
    }

    /**
     *给目标对象生成代理对象
     */

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //执行目标对象方法
                        Object returnObject = method.invoke(subject,args);
                        return returnObject;
                    }
                }
        );
    }
}

public class TestDynamicSubject {
    public static void main(String[] args) {
        //真实对象引用
        Subject subject = new RealSubject();
        //通过代理对象工厂类,获得该目标对象的代理对象引用
        Subject proxySubject = (Subject) new ProxyFactory(subject).getProxyInstance();
        proxySubject.doSomeThing();
    }
}
jdk提供的动态代理类。必须要有接口。jdk代理类是这样一种Class:它在运行时生成Class,在生成它时,你必须提供一组interface给他。然后该Class就宣称实现了这些Interface。


Cglib代理

假如类没有接口,单单一个对象,可以使用Cglib代理。

Cglib代理也叫子类代理。他是在内存中构建一个子类对象。从而实现对目标功能的扩展

广泛被许多aop框架使用,为他们的方法提供拦截

Cglib子类代理实现方法

1.引入jar包。spring-core.jar

2.代理的类不能为final/static.否则将不会拦截到

/**
 * (没有接口)真实对象
 *
 * @author LiJie
 * @create 2018/1/19 15:29
 */
public class Subject {

    public void doSomething() {
        System.out.println("我是真实角色");
    }
}


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

import java.lang.reflect.Method;

/**
 * Cglib代理工厂类。在内存中动态构建一个子类对象
 *
 * @author LiJie
 * @create 2018/1/19 15:31
 */
public class ProxyFactory implements MethodInterceptor {
    //需要维护的对象
    private Object subject;

    public ProxyFactory(Object subject) {
        this.subject = subject;
    }
/**
 * set好之后,就可以创建代理对象
 * @return
 */
public Object getProxyInstance() {
    //1.工具类
    Enhancer en = new Enhancer();
    //2.设置父类
    en.setSuperclass(subject.getClass());
    //3.设置回调函数
    en.setCallback(this);
    //创建子类代理对象
    return en.create();
}

/**
 * 测试类
 *
 * @author LiJie
 * @create 2018/1/19 15:40
 */
public class Test {

    public static void main(String []args){
        Subject subject = new Subject();
        Subject proxySubject = (Subject)new ProxyFactory(subject).getProxyInstance();
        proxySubject.doSomething();
    }
}
文中代码:http://www.cnblogs.com/cenyu/p/6289209.html

你可能感兴趣的:(设计模式)