设计模式-代理模式(Proxy)

代理模式

静态代理

【角色分析】

  • 抽象角色:一般会使用【接口/抽象类】解决
  • 真实角色:被代理角色
  • 代理角色:代理真实角色,代理后一般会做一些附属操作
  • 客户:访问代理对象的人

【代码步骤】

  1. 接口
package cn.iris.demo01;

/**
 * @author Iris 2021/8/12
 */
// 租房
public interface Rent {

    public void rent();
}
  1. 真实角色
package cn.iris.demo01;

/**
 * @author Iris 2021/8/12
 */
// 房东
public class Host implements Rent {

    @Override
    public void rent() {
        System.out.println("房东出租房子...");
    }
}
  1. 代理角色
package cn.iris.demo01;

/**
 * @author Iris 2021/8/12
 */
public class Proxy implements Rent{
    private Host host;

    public Proxy() {
    }

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

    @Override
    public void rent() {
        visitHouse();
        fare();
        sign();
        host.rent();
    }

    /**
     * 看房
     */
    public void visitHouse() {
        System.out.println("中介带你看房...");
    }

    /**
     * 收中介费
     */
    public void fare() {
        System.out.println("中介收你钱...");
    }

    /**
     * 签合同
     */
    public void sign() {
        System.out.println("中介和你签租赁合同...");
    }
}
  1. 客户端访问代理角色
package cn.iris.demo01;

/**
 * @author Iris 2021/8/12
 */
public class Client {
    public static void main(String[] args) {
        // 房东:想租房子
        Host host = new Host();
        // 代理:中介帮房东租房子,同时增加附属操作
        Proxy proxy = new Proxy(host);
        // 用户:不用找房东,直接接触中介租房子
        proxy.rent();
    }
}

【代理模式的好处】

  • 使真实角色的操作更加纯粹,不用关注一些公共业务
  • 公共业务交予代理角色负责,实现了业务分工
  • 公共业务扩展时,方便集中管理
  • 在项目中可避免对原业务代码进行修改而导致项目崩溃【避免了‘刨祖坟’(狗头)

【缺点】

  • 一个真实角色会产生一个代理角色,多个真实角色会产生大量代码,降低开发效率

动态代理

  • 动态代理与静态代理中的角色相同
  • 动态代理的代理类动态生成
  • 动态代理分为两类:基于接口的动态代理,基于类的动态代理
    • 基于接口的动态代理---JDK动态代理
    • 基于类的动态代理---cglib
    • Java字节码实现:javassist(JBoss服务器)
      需要了解两个了:Proxy,InvocationHandler(调用处理程序)

代码实现

  • UserService接口
package cn.iris.demo02;

/**
 * @author Iris 2021/8/12
 */
public interface UserService {
    void add();
    void del();
    void update();
    void query();
}
  • UserServiceImpl实现类
package cn.iris.demo02;

/**
 * @author Iris 2021/8/12
 */
public class UserServiceImpl implements UserService{

    @Override
    public void add() {
        System.out.println("增加一个用户");
    }

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

    @Override
    public void update() {
        System.out.println("更新一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询一个用户");
    }
}
  • 动态实现类【重要--可做工具类使用】
package cn.iris.demo04;

import cn.iris.demo03.Rent;

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

/**
 * 使用该类动态生成代理类
 * @author Iris 2021/8/12
 */
public class ProxyInvocationHandler implements InvocationHandler {

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

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

    /**
     * 生成得到代理类
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(
                this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);
    }

    /**
     * 处理代理实例并返回结果
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 动态代理本质:使用【反射机制】实现
        log(method.getName());
        Object res = method.invoke(target, args);
        return res;
    }

    public void log(String msg) {
        System.out.println("使用了"+msg+"方法");
    }
}
  • 用户端使用动态代理生成代理类,调用真实类的方法
package cn.iris.demo04;

import cn.iris.demo02.UserService;
import cn.iris.demo02.UserServiceImpl;

/**
 * @author Iris 2021/8/12
 */
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();
        proxy.del();
        proxy.update();
        proxy.query();
    }
}

【动态代理的好处】

  • 静态代理的所有好处
  • 一个动态代理类代理的是一个接口,即是对应的一类业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口
posted @ 2021-08-12 16:53  菜鸢爱敲bug  阅读(55)  评论(0编辑  收藏  举报