设计模式-代理

代理

代理:我们应该不陌生,最常见的就是我们身边的一些朋友,在朋友圈里边卖东西的人,她们从厂家拿货,然后在朋友圈里边卖给熟人

在这里插入图片描述

按道理来说,客户可以直接去找厂家来买,但是呢,现实生活中很少能看到这样的场景,一般都是厂家把货物给代理商,代理商再把货物卖给客户

所以代理商就有点中介的意味

静态代理

静态代理:是在不改变原有代码的基础上,增强功能
代理(Proxy)和厂家(manufactor)都实现资源接口(Resourcesable)中的方法(method())代理的method方法是调用厂家的method方法,此时客户(Client)只需要实现代理中的method方法就是实现了厂家的method方法。

在这里插入图片描述


下边看一个具体的例子(租房子)

1、资源接口

package com.zkw.Demon01;

public interface Rent {
    public void rentHouse();
}

2、真是角色

package com.zkw.Demon01;

//房东要出租房子
public class Landlord implements Rent {
    public void rentHouse() {
        System.out.println("房东:我要出租房子");
    }
}

3、代理角色

package com.zkw.Demon01;

//中介,房东把房子放到中介所
public class Intermediate implements Rent {
    private Landlord landlord;

    public Intermediate() {
    }

    public Intermediate(Landlord landlord) {
        this.landlord = landlord;
    }

    //在Spring中一般使用Set方法来注入 而不是通过有参构造
  /*  public void setLandlord(Landlord landlord) {
        this.landlord = landlord;
    }*/

    public void seeHouse(){
        System.out.println("中介:带领租客去看房");
    }

    public void rentHouse(){
        landlord.rentHouse();
    }

    public void contract(){
        System.out.println("中介:代替房东和租客签租赁合同");
    }

    public void charge(){
        System.out.println("中介;收取费用");
    }
}

4、用户

package com.zkw.Demon01;

//租客要租房子
public class Tenant {
    public static void main(String[] args) {
        //房东
        Landlord landlord = new Landlord();
        //中介:找到房东,拿到房源,并带领租客去看房
        //构造器注入
        Intermediate intermediate = new Intermediate(landlord);
        
        //Spring中通过set方法注入
       // intermediate.setLandlord(landlord);
        
        //房东的业务
        intermediate.rentHouse();
        //中介附加的业务
        intermediate.seeHouse();
        intermediate.contract();
        intermediate.charge();

    }
}

用户需要租房子,而房东需要出租房子,房东把房子给中介让中介帮忙出租,此时中介就相当于是房东,而用户找到中介让中介帮忙找房子,他要租房子,此时中介带领用户去看房子,如果用户要租就签房屋租赁合同。

结果如图

在这里插入图片描述

代理模式的优缺点:

  • 优点
    • 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
    • 公公也就是交给代理角色,实现了业务的分工
    • 公共业务发生扩展的时候,方便集中管理
  • 缺点:
    • 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率低

动态代理

动态代理主要是运用了反射的机制来实现的

通过使用Proxy提供的方法来生成代理类,通过查看jdk1.8-api它提供了两种方法来创建代理类

在这里插入图片描述

在这里插入图片描述

解释三个东西:

  • ClassLoader:类的加载器
  • interfaces:代理类实现接口
  • h:调度方法给处理函数

下边看一个具体的例子:

package com.zkw.Demon03;

public interface UserService {
    public void add();
    public void del();
    public void modify();
    public void query();
}
package com.zkw.Demon03;

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

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

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

    public void query() {
        System.out.println("查询了一个用户");
    }
}
package com.zkw.Demon03;

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

public class PoxyInvocationHandler implements InvocationHandler {

    private Object target;

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

    //生成代理类 this 是因为我们当前类实现了InvocationHandler中的调度方法invoke
    public Object getProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

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

    public void log(String msg){
        System.out.println("使用来"+msg+"方法");
    }
}
package com.zkw.Demon03;

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

或者把 PoxyInvocationHandler这个类换成Invocation

package com.zkw.Demon03;

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

public class Invocation implements InvocationHandler {

    private Object target;

    public Invocation(Object target) {
        this.target = target;
    }
    /**
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     */

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

    public void log(String msg){
        System.out.println("使用来"+msg+"方法");
    }
}

package com.zkw.Demon03;

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

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        InvocationHandler invocation = new Invocation(userService);

        //创建一个代理的对象
        UserService userProxy1 = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(),
                new Class<?>[]{UserService.class}, invocation);
        
         /*  UserService userProxy1 = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
              userService.getClass().getInterfaces(), invocation);*/
        //执行方法
        userProxy1.add();
        userProxy1.del();
        userProxy1.modify();
        userProxy1.query();
    }
}

结果如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值