设计模式-结构型-代理模式

141 阅读2分钟

简介

代理模式是结构型模式的一种,在大型项目中十分常见,比如大名鼎鼎的Spring,其AOP的核心就是动态代理,还有Spring data其对数据库操作的底层也是用了动态代理。在生活中,代理模式也十分常见,比如你要去请一个明星做商演,你不会去直接找明显本人而是去找其经纪人,其中经纪人就是充当了代理角色。代理模式分为两种,动态代理和静态代理,下面分别是其代码实现的demo。

静态代理

以明星接商演为例: 1.首先定义明星的接口

public interface Star {
    void play();
}

2.定义歌手来实现明星的接口

public class Singer implements Star{
    @Override
    public void play() {
        System.out.println("I will sing");
    }
}

3.定义经纪人角色,此角色是代理角色并实现了明星接口,负责明星商演的前后工作。

public class StarProxy implements Star{

    private Star star;

    public StarProxy(Star star) {
        this.star = star;
    }
    @Override
    public void play() {
        System.out.println("proxy start interactive");
        this.star.play();
        System.out.println("proxy accept money");
    }
}

4.客户端调用,此时应该去找代理类,而不是明星本人。

public class Test {
    public static void main(String[] args) {
        Star mike = new Singer();
        Star mikeProxy = new StarProxy(mike);
        mikeProxy.play();
    }
}

动态代理

对于动态代理,有jdk和cglib两种实现方式,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则代理失效。cglib是针对类来实现代理的,其原理是针对指定的目标实现一个子类,并覆盖其中的方法增强。

JDK动态代理

1.首先定义明星的接口

public interface Star {
    void play();
}

2.定义歌手来实现明星的接口

public class Singer implements Star{
    @Override
    public void play() {
        System.out.println("I will sing");
    }
}

3.定义经纪人角色,此角色是代理角色并实现了明星接口,负责明星商演的前后工作。

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

public class StarProxy implements InvocationHandler {

    private Object object;

    public StarProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy start interactive");
        method.invoke(object, args);
        System.out.println("proxy accept money");
        return null;
    }
}

4.客户端调用

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

public class Test {
    public static void main(String[] args) {
        Star mike = new Singer();
        InvocationHandler handler = new StarProxy(mike);
        Star proxy = (Star) Proxy.newProxyInstance(mike.getClass().getClassLoader(), mike.getClass().getInterfaces(), handler);
        proxy.play();
    }
}

cglib动态代理

准备工作:cglib的maven坐标

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

1.首先定义明星的接口

public interface Star {
    void play();
}

2.定义歌手来实现明星的接口

public class Singer implements Star{
    @Override
    public void play() {
        System.out.println("I will sing");
    }
}

3.定义经纪人角色,此角色是代理角色并实现了明星接口,负责明星商演的前后工作。

mport net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class StarProxy implements MethodInterceptor {

    private Object target;

    public Object getTarget(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("proxy start interactive");
        methodProxy.invokeSuper(object, args);
        System.out.println("proxy accept money");
        return null;
    }
}

4.客户端调用

public class Test {
    public static void main(String[] args) {
        StarProxy proxy = new StarProxy();
        Singer mike = new Singer();
        Star mikePorxy = (Singer)proxy.getTarget(mike);
        mikePorxy.play();
    }
}