JAVA 设计模式 - 代理模式

262 阅读2分钟

代理模式

代理的好处

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

代理模式的分类

静态代理

静态代理的实现步骤

  • 抽象具体业务
  • 真实角色实现或继承抽象接口
  • 代理角色实现或继承抽象接口
  • 客户端访问代理类

静态代理的缺点

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

案例 1

1:
// 抽象角色 - 租房方法
public interface RentDao {
    // 租房
    void rent();

}
2:
// 真实角色 - 房东
public class Host implements RentDao{
    @Override
    public void rent() {
        System.out.println("房东出租房子!");
    }
}

3:
// 代理类(中介)
public class AgentProxy implements RentDao{

    private Host host;

	// Spring 不建议使用有参构造方法注入
    //public AgentProxy(Host host){
    //    this.host = host;
    //}
    public void setAgentProxy(Host host){
        this.host = host;
    }

    @Override
    public void rent() {
        this.lookHose();
        host.rent();
        this.hetong();
    }

    // 切入其他操作
    private void lookHose(){
        System.out.println("中介带领看房子");
    }

    // 切入其他操作
    private void hetong(){
        System.out.println("中介带领签合同");
    }
}

4:
// 访问代理的人 - 租房者
public class User {

    public static void main(String[] args) {
        Host host = new Host();
        AgentProxy agent = new AgentProxy();
        agent.setAgentProxy(host);
        agent.rent();
    }
}

案例 1 - 记录日志功能


public interface UserService {

    void add();
    void delete();
    void update();
    void query();

}

public class UserServiceImpl implements UserService{

    @Override
    public void add() {
        System.out.println("add...");
    }

    @Override
    public void delete() {
        System.out.println("delete...");
    }

    @Override
    public void update() {
        System.out.println("update...");
    }

    @Override
    public void query() {
        System.out.println("query...");
    }
}

public class HandlerProxy implements UserService{

    private UserService userService;

    public void setUserService(UserService userService){
        this.userService = userService;
    }


    @Override
    public void add() {
        this.log("add");
        userService.add();
    }

    @Override
    public void delete() {
        this.log("delete");
        userService.delete();
    }

    @Override
    public void update() {
        this.log("update");
        userService.update();
    }

    @Override
    public void query() {
        this.log("query");
        userService.query();
    }
    // 日志方法
    void log(String action){
        System.out.println("进行了" + action + "操作");
    };
}

public class Test {
    public static void main(String[] args) {
        HandlerProxy handlerProxy = new HandlerProxy();
        UserService userService = new UserServiceImpl();
        handlerProxy.setUserService(userService);
        handlerProxy.add();
    }

}

#
进行了add操作
add...

动态代理

为了解决静态代理的缺点,应使用动态代理。可以代理多个类。
动态代理的和静态代理所代理的角色一样。
动态代理的代理类是动态生成的,本质是反射实现的。

动态代理方式

  • 基于接口的动态代理 - JDK 的动态代理
  • 基于类的动态代理 - cglib
  • Java字节码 - Javassit

动态代理的两个重要的类

java.util.reflect 包下:
1. Proxy - 生成代理类
2. InvocationHandler 接口,反射包 - 调用处理程序,处理代理实例并返回一个结果

动态代理实现

public interface UserService {

    void add();
    void delete();
    void update();
    void query();
}

public class UserServiceImpl implements UserService{

    @Override
    public void add() {
        System.out.println("add...");
    }

    @Override
    public void delete() {
        System.out.println("delete...");
    }

    @Override
    public void update() {
        System.out.println("update...");
    }

    @Override
    public void query() {
        System.out.println("query...");
    }
}


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

public class ProxyInvicationHandler implements InvocationHandler {

    // 被代理的接口
    private Object target;

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

    // 生成代理类,继承抽象接口
    public Object getProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                this.getClass().getInterfaces(), this);
    }

    // 处理代理实例,返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target);
        return result;
    }

    void log(String action){
        System.out.println("执行了" + action + "方法");
    }
}


public class Test {

    public static void main(String[] args) {
        // 真实角色
        UserServiceImpl userService = new UserServiceImpl();
        ProxyInvicationHandler pih = new ProxyInvicationHandler();
        pih.setTarget(userService);
        UserService proxy = (UserService) pih.getProxy();
        proxy.add();
    }

}