美文网首页程序员Java学习笔记
简单易懂设计模式 之 代理(proxy)

简单易懂设计模式 之 代理(proxy)

作者: 简xiaoyao | 来源:发表于2017-10-14 22:11 被阅读53次

现实生活中代理很常见,在设计领域代理模式也经常被使用,它的意义在于为其他对象提供代理层以控制对这个对象的访问

使用场景

当某个接口不方便直接被调用时,就考虑使用代理模式对其进行封装,并添加必要的控制逻辑,如:

  • 权限控制,即在特定逻辑处插入权限控制代码
  • 对象保护,即客户端不能直接操纵某对象,但又必须与该对象有所交互

代码示例

代理分为静态代理与动态代理两种。这里的静态与动态和软件开发里经常提及的静态/动态意思相近,即前者代表死的,后者代表活的,啥意思呢?即:静态代理一次只能代理一个业务实现,针对多个业务实现就需要多个静态代理类进行代理;而动态代理类可以对同一接口下一系列的业务实现进行统一代理,增加了灵活性,如大名鼎鼎的AOP(面向切面编程)其实现机制就是动态代理

静态代理:

//被代理接口
public interface Image {
    public void loadImage();
}

//被代理实现
public class ViewImage implements Image{
    @Override
    public void loadImage() {
        System.out.println("ViewImage load image");
    }
}

//代理类
public class ImageProxy implements Image{
    private Image targetImage;
    public ImageProxy(Image targetImage) {
        this.targetImage = targetImage;
    }

    @Override
    public void loadImage() {
        System.out.println("ImageProxy begin");
        this.targetImage.loadImage();
        System.out.println("ImageProxy ends");
    }
}

//客户端调用
public class ImageClient {
    public static void main(String[] args) {
        ImageProxy imageProxy = new ImageProxy(new ViewImage());
        imageProxy.loadImage();
    }
}

//运行结果
ImageProxy begin
ViewImage load image
ImageProxy ends

增加代理后,可以方便的在被代理的业务逻辑前后增加控制逻辑;

动态代理:

//被代理接口
public interface Image {
    public void loadImage();
}

//被代理实现
public class PersonImage implements Image {
    @Override
    public void loadImage() {
        System.out.println("PersonImage load image");
    }
}

//被代理实现
public class ViewImage implements Image {
    @Override
    public void loadImage() {
        System.out.println("ViewImage load image");
    }
}

//代理类
public class ImageHandler implements InvocationHandler{
    private Object target;

    public Object getProxy(Object target) {
        this.target = target;
        Object result = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        return result;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("ImageHandler begin");
        Object result = null;
        try{
            result = method.invoke(this.target,args);
        }catch(Exception e){
            e.printStackTrace();
        }
        return result;
    }
}

//客户端调用
public class ImageClient {
    public static void main(String[] args) {
        ImageHandler imageHandler = new ImageHandler();
        Image personImageProxy = (Image)imageHandler.getProxy(new PersonImage());
        Image viewImageProxy = (Image)imageHandler.getProxy(new ViewImage());
        personImageProxy.loadImage();
        viewImageProxy.loadImage();
    }
}

//运行结果
ImageHandler begin
ViewImage load image
ImageHandler begin
ViewImage load image

上例是通过Java本身提供的针对动态代理的支持接口进行实现,实现其接口即可达到动态代理的效果,当然,除开通过JDK实现动态代理,比较常用的动态代理实现方式还有通过CGLIB,这里就不做详细介绍

应用实例

java.lang.reflect.Proxy
Apache Commons Proxy

相关文章

网友评论

    本文标题:简单易懂设计模式 之 代理(proxy)

    本文链接:https://www.haomeiwen.com/subject/vuslyxtx.html