20210507—Java_Proxy—代理模式简介

Proxy学习记录

一、代理模式

代理是基于反射机制,使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑

1、什么是代理

举例:

代购, 中介,换ip,商家等等

  比如有一家美国的大学, 可以对全世界招生。 留学中介(代理)

  留学中介(代理): 帮助这家美国的学校招生,  中介是学校的代理, 中介是代替学校完成招生功能。
     代理特点:
       1. 中介和代理他们要做的事情是一致的:  招生。 
       2. 中介是学校代理, 学校是目标。
       3. 家长---中介(学校介绍,办入学手续)----美国学校。
       4. 中介是代理,不能白干活,需要收取费用。
       5. 代理不让你访问到目标。

     为什么要找中介 ? 
       1. 中介是专业的, 方便
       2. 家长现在不能自己去找学校。 家长没有能力访问学校。 或者美国学校不接收个人来访。

     
     买东西都是商家卖, 商家是某个商品的代理, 你个人买东西, 肯定不会让你接触到厂家的。

2、需要代理的原因

例如: 有 A,B,C 三个类, A 原来可以调用 C 类的方法, 现在因为某种原因 C 类不允许A 类调用其方法,但 B 类可以调用 C 类的方法。

A 类通过 B 类调用 C 类的方法。这里 B 是 C的代理。

A 通过代理 B 访问 C.

在这里插入图片描述
在这里插入图片描述

3、代理的作用

1.功能增强: 在你原有的功能上,增加了额外的功能。 新增加的功能,叫做功能增强。

2.控制访问: 代理类不让你访问目标,例如商家不让用户访问厂家。

4、代理模式分类

静态代理和动态代理

二、静态代理实现

静态代理是指,代理类在程序运行前就已经定义好.java 源文件,其与目标类的关系在
程序运行前就已经确立。

在程序运行前代理类已经编译为.class 文件。

1、静态代理

1)代理类是自己手工实现的,自己创建一个java类,表示代理类。

2)同时你所要代理的目标类是确定的。

2、优点/缺点

1)优点:实现简单;容易理解

2)缺点:当目标类增加了, 代理类可能也需要成倍的增加,最终代理类数量过多;
当你的接口中功能增加或修改,会影响众多的实现类、厂家类,代理都需要修改

3、举例

模拟一个用户购买u盘的行为。
		   用户是客户端类
		   商家:代理,代理某个品牌的u盘。
		   厂家:目标类。

	三者的关系: 用户(客户端)---商家(代理)---厂家(目标)
		商家和厂家都是卖u盘的,他们完成的功能是一致的,都是卖u盘。

1)创建一个接口,定义卖u盘的方法, 表示你的厂家和商家做的事情。

// UsbSell.java
package com.bjpowernode.service;

public interface UsbSell {

    float sell(int amount);
}

2)创建厂家类,实现1步骤的接口

// UsbKingFactory.java
package com.bjpowernode.factory;
import com.bjpowernode.service.UsbSell;

public class UsbKingFactory implements UsbSell {

    @Override
    public float sell(int amount){
        System.out.println("King's USB disk");
        return 85.0f;
    }
}

3)创建商家,就是代理,也需要实现1步骤中的接口。

// TaoBao.java
package com.bjpowernode.Saler;
import com.bjpowernode.factory.UsbKingFactory;
import com.bjpowernode.service.UsbSell;

public class TaoBao implements UsbSell {

    private UsbKingFactory factory = new UsbKingFactory();

    @Override
    public float sell(int amount) {
        float price = factory.sell(1);

        price = price + 25;
        System.out.println("感谢购买,赠送一张优惠券");
        return price;
    }
}

4)创建客户端类,调用商家的方法买一个u盘。

// Market.java
package com.bjpowernode;
import com.bjpowernode.Saler.TaoBao;
import com.bjpowernode.factory.UsbKingFactory;

public class Market {
    public static void main(String[] args) {
        TaoBao taoBao = new TaoBao();
        float price = taoBao.sell(1);
        System.out.println("通过淘宝购买U盘的单价:" + price);

        UsbKingFactory usbKingFactory = new UsbKingFactory();
        float price1 = usbKingFactory.sell(1);
        System.out.println("淘宝在厂家直接购买U盘单价:" + price1);
    }
}

4、动态代理

在静态代理中目标类很多时候,可以使用动态代理,避免静态代理的缺点

  • 1)代理类数量可以很少,
  • 2)当你修改了接口中的方法时,不会影响代理类。

在程序执行过程中,使用jdk的反射机制,创建代理类对象, 并动态的指定要代理目标类
动态代理是一种创建java对象的能力,让你不用创建代理类,就能创建代理类对象

5、动态代理的实现

java 语言通过 java.lang.reflect 包提供三个类支持代理模式 Proxy, Method, InovcationHandler

1)InvocationHandler 接口(调用处理器):就一个方法invoke()
invoke():表示代理对象要执行的功能代码。
你的代理类要完成的功能就写在invoke()方法中。

2)Method类:表示方法的, 确切的说就是目标类中的方法。
作用:通过Method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法的参数)

3)Proxy类:核心的对象,创建代理对象。之前创建对象都是 new 类的构造方法()
现在我们是使用Proxy类的方法,代替new的使用。
方法: 静态方法 newProxyInstance()
作用是: 创建代理对象, 等同于静态代理中的TaoBao taoBao = new TaoBao();

6、举例

通过动态代理完成模拟一个用户购买u盘的行为。
		   用户是客户端类
		   商家:代理,代理某个品牌的u盘。
		   厂家:目标类。

1)创建接口,定义目标类要完成的功能

// UsbSell.java
package com.bjpowernode.service;

public interface UsbSell {
    float sell(int amount);
}

2)创建目标类实现接口

// UsbKingFactory.java
package com.bjpowernode.factory;
import com.bjpowernode.service.UsbSell;

// 目标类
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        // 目标方法
        System.out.println("此为目标类,执行了目标方法");
        return 85.0f;
    }
}

3)创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
调用目标方法;增强功能

// MySellHandler.java
package com.bjpowernode.handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// 必须实现InvocationHandler接口,完成代理类要做到功能
// 即 1.调用目标方法;2.功能增强
public class MySellHandler implements InvocationHandler {

    private Object target = null;

    // 动态代理:目标对象是活动的,不是固定的,需要传入进来
    // 传入的是谁,就给谁创建代理
    public MySellHandler(Object target){
        // 给目标对象赋值
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object res = null;
        res = method.invoke(target, args);  // 执行目标方法

        // 功能增强
        if(res != null){
            Float price = (Float)res;
            price = price + 25;
            res = price;
        }

        // 其他功能
        System.out.println("欢迎购买,赠送淘宝优惠券");

        return res;
    }
}

4)使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。

// MainShop.java
package com.bjpowernode;

import com.bjpowernode.factory.UsbKingFactory;
import com.bjpowernode.handler.MySellHandler;
import com.bjpowernode.service.UsbSell;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class MainShop {
    public static void main(String[] args) {
        // 创建代理对象,使用Proxy
        // 1.创建目标对象
        UsbSell factory = new UsbKingFactory();
        // 2.创建InvocationHandler对象,传入目标对象
        InvocationHandler handler = new MySellHandler(factory);
        // 3.创建代理对象
        UsbSell proxy = (UsbSell)Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), handler);
        // 4.通过代理执行方法
        float price = proxy.sell(1);
        System.out.println("通过动态代理,调用方法:" + price);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值