03、代理模式

代理模式

10.1、静态代理

1、代理模式的优点

也就是为什么用代理模式?

  • 代理模式符合类的构造原则,使类职责分明
  • 公共的业务由代理来完成 . 实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便 .
  • 就拿下面个例子来说:房东只有租房子方法,顾客找代理,代理可以做代理该做的事情
  • 使真实类更加纯粹
  1. 接口
public interface Rent {
    void rentHouse();
}

2、被代理的对象

public class Host implements Rent{
    private String name;

    public Host(String name) {
        this.name = name;
    }

    public void rentHouse() {
        //房东只做一件事就是租房子,他不带客户看房子什么的
        System.out.println("房东"+name+"出租房子!");
    }
}

3、静态代理

package bing;

/**
 * @author zhangbingbing
 * @version 1.0
 * @date 2020/5/18 17:03
 */
public class Proxy implements Rent {
    private Host host;

    public void setHost(Host host) {
        this.host = host;
    }

    //代理就可以做很多事情了
    public void rentHouse() {
        //还是调用房租的租房子方法
        lookHouse();
       host.rentHouse();
       hetong();
       cost();
    }

    private void lookHouse() {
        System.out.println("带顾客看房子");
    }

    private void hetong() {
        System.out.println("签合同");
    }

    private void cost() {
        System.out.println("收房租");
    }
}

4、顾客

public class Client {
    //客户要去租房子
    public static void main(String[] args) {
        Host host = new Host("bingbing");	//一定要有哥真正的房租
        Proxy proxy = new Proxy();
        proxy.setHost(host);
        proxy.rentHouse();
    }
}

各个类的值则分明,增加了效率和可读性

  • 在实际开发中的用处

直接在service层加了一个UserService代理,在不改变原来类的基础上增加了日志功能!

package bing.demo2.service;

/**
 * @author zhangbingbing
 * @version 1.0
 * @date 2020/5/18 17:48
 */
public class UserProxy implements UserService {
    private UserServiceImpl userService;

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

    public void add() {
        log();
        userService.add();
    }

    public void delete() {
        log();
        userService.delete();
    }

    public void update() {
        log();
        userService.update();
    }

    public void query() {
        log();
        userService.query();
    }

    private void log() {
        System.out.println("打印了日志");
    }
}

10.2、动态代理

JDK实现动态代理需要两个类:

  • 反射包下的Proxy : 用来返回要代理的实例
  • InvocationHandler : 执行代理的方法

  • 代码

  • 动态代理:可以代理任何类

优点:我们不需要像静态代理一个类型的类必须跟一个代理,这里可以说是一个工具类,每一个类都可以拿来用,

底层利用反射的机制实现,而且静态代理必须和实例实现同一个接口,而有些方法代理并不需要实现,增加了代码冗余。

package bing.demo3;

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

/**
 * @author zhangbingbing
 * @version 1.0
 * @date 2020/5/23 19:01
 */
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 {
        //用反射来实现
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}
  • 测试
public class Client {

    public static void main(String[] args) {
        //都需要一个代理的实例对象
        Host host = new Host("小张");
        ProxyInvocationHandler phl = new ProxyInvocationHandler();
        phl.setTarget(host);//设置被代理的对象
        Rent proxy = (Rent) phl.getProxy();	//获取代理对象
        proxy.rentHouse();		//执行被代理对象的方法
    }
}

总结:两个类很重要,反射包下的

  • Proxy : 获取代理对象
  • InvocationHandler : 执行被代理对象的方法

步骤:

  1. 设置被代理的对象
  2. 获取代理对象
  3. 执行代理方法
posted @ 2020-06-15 23:34  贝加尔湖畔╭  阅读(122)  评论(0编辑  收藏  举报