Java设计模式---静态代理和动态代理

Java设计模式---静态代理和动态代理,第1张

一、静态代理

假设一个场景,一个客户需要租房,然后找到中介,中介那里有很多房源。房东负责出租,那么中介就带客户去:(1)看房 (2)房东出粗(3) 签合同 (4)收中介费

①创建一个房东接口并创建一个具体的房东实现这个接口

public interface Rent {
    void rent(); //出租
}
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房屋");
    }
}

②创建一个代理对象(中介) 调用房东租房并附带一些其他的 *** 作

public class Proxy {

    private Host host;

    public Proxy(Host host) {
        this.host = host;
    }
    public void rent(){
        System.out.println("带看房");
        host.rent();
        System.out.println("签合同");
        System.out.println("收房租");
    }
}

③测试

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host); //中介帮房东租房子 但是呢 中介会进行一些附加的 *** 作
        proxy.rent();
    }
}

//打印
// 带看房
// 房东出租房屋
// 签合同
// 收房租

说白了就是对某个具体的类中的方法进行了增强。不影响被代理类的 *** 作的同时对代理类的 *** 作进行了增强.

优点:

  • 可以时被代理的类的功能更加纯粹,不用去关注一些公共的业务
  • 公共业务交给了代理它的类,实现了业务的分工
  • 也便于公共业务发生扩展

缺点:

  • 一个被被代理的类就得产生一个代理他的类,代码量会增加,开发效率会变低。
二、动态代理
  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    基于接口–JDK动态代理
    基于类:cglib动态代理

需要了解两个类:
Proxy(代理),提供创建代理类实例的静态方法
InvocationHandler(调用处理程序):每个代理对象都需要一个InvocationHandler去进行关联,代理对象调用方法时会调用InvocationHandler中的invoke方法,然后我们可以在这个方法中对被代理中的方法进行增强。

①创建一个房东接口并创建一个具体的房东实现这个接口

public interface Rent {
    void rent();
}
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房屋");
    }
}

②创建一个用来生成代理对象的类

//等会儿我们用这个类 ,自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {

    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成一个代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(rent.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }

    //处理代理实例并返回处理结果  (这个方法是生成的代理类调用方法是自动调用的,相当于这个方法会拦截代理对象调用的方法 然后对该方法进行增强)
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("看房");
        Object result = method.invoke(rent, args);//通过反射 执行rent中的方法
        //打印被调用的方法的名称
       // System.out.println(method.getName());
        System.out.println("签合同");
        System.out.println("收中介费");
        return result;
    }


}

③测试

public class Client {
    public static void main(String[] args) {
        //真实角色(被代理的对象)
        Host host = new Host();
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setRent(host);//设置要代理的对象
        //拿到我们的代理对象
        Rent proxy = (Rent) pih.getProxy();
        proxy.rent();
    }
}

//执行结果打印
//看房
//房东出租房屋
//签合同
//收中介费

注意:当然 这个地方可以变得更加万能和灵活,将ProxyInvocationHandler 中的Rent换成Object,这样我们想对哪个类进行代理都行.

动态代理的好处:

  • 可以使真实角色的 *** 作更加纯粹!不用去关注一些公共的业务.
  • 公共业务就交给代理对象!实现业务的分工!
  • 不用像静态代理那样对于每一个需要被代理的类都手写一个代理类。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/871065.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存