首页 > 技术文章 > Java设计模式之代理模式

ctks 2020-10-03 23:41 原文

代理模式

应用场景

假设现在项目经理有一个需求:在项目现有所有类的方法前后打印日志。

如何在不修改已有代码的前提下,完成这个需求?

答案就是代理

静态代理

优点

  • 可以使真实角色的操作更加纯粹!不用去关注一 些公共的业务
  • 公共也就就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!

缺点:

  • 一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率会变低

代码部分

创建Rent接口

package com.wuxin.damo01;

public interface Rent {
    public void rent1();
    public void rent2();
}

创建Rent接口的实现类

package com.wuxin.damo01;

public class Host implements Rent {
    public void rent1() {
        System.out.println("我想要出租一套四合院");
    }

    public void rent2() {
        System.out.println("我想要出租一套空中阁楼");
    }
}

创建代理对象

package com.wuxin.damo01;

public class Proxy implements Rent{
    private Host host;

    public Proxy(Host host) {
        this.host = host;
    }

    public Proxy() {
    }

    public void rent1() {
        host.rent1();
        contract();
        money();
    }

    public void rent2() {
        host.rent2();
        contract();
        money();
    }
    public void contract() {
        System.out.println("签租赁合同");
    }
    public void money() {
        System.out.println("收租金");
    }
}

创建测试对象

package com.wuxin.damo01;

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent1();
        proxy.rent2();
    }
}

日志

我想要出租一套四合院
签租赁合同
收租金
我想要出租一套空中阁楼
签租赁合同
收租金

Process finished with exit code 0

动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口--- JDK动态代理[我们在这里使用]
    • 基于类: cglib
    • java字节码实现: javasist

总体来说,静态代理的优点他都有,静态代理的缺点他也避过了

需要了解两个类: Proxy:代理,InvocationHandler: 调用处理程序

代码部分

首先创建一个UserService接口

package com.wuxin.damo02;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

创建一个实现类去实现这个接口

package com.wuxin.damo02;

public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("新增一个用户");
    }

    public void delete() {
        System.out.println("删除一个用户");
    }

    public void update() {
        System.out.println("修改一个用户");
    }

    public void query() {
        System.out.println("查询一个用户");
    }
}

创建一个代理类(可作为工具类)

package com.wuxin.damo02;

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

public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

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

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }
    public void log(String msg){
        System.out.println("[日志]:执行了" + msg + "方法");
    }
}

创建一个用户去测试代理

package com.wuxin.damo02;

public class Client{
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(userService);
        UserService proxy = (UserService) pih.getProxy();
        proxy.add();
    }
}

日志输出:

[日志]:执行了add方法
新增一个用户

Process finished with exit code 0

推荐阅读