ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【java】代理模式简单实现

2022-01-28 19:01:17  阅读:89  来源: 互联网

标签:java 对象 创建 代理 模式 UsbSell 接口 public


概念

代理模式(Proxy Pattern)是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。在代理模式中,一个类代表另一个类的功能,我们创建具有现有对象的对象,以便向外界提供功能接口。

目的

  • 控制访问:为其他对象提供一种代理以控制对这个对象的访问。
  • 功能增强:完成目标对象的调用时,可附加一些额外功能。

问题

为什么要控制对于某个对象的访问呢? 举个例子: 有这样一个消耗大量系统资源的巨型对象, 你只是偶尔需要使用它, 并非总是需要。

解决方法

增加中间层,关键代码实现与被代理类组合。

新建一个与原服务对象接口相同的代理类, 然后更新应用以将代理对象传递给所有原始对象客户端。 代理类接收到客户端请求后会创建实际的服务对象, 并将所有工作委派给它。

 实际应用

1、Windows 里面的快捷方式,连接到真正应用程序。

2、买车不是直接去造车厂而是4s店。

3、spring aop(面向切片编程)。

具体例子:

信用卡是银行账户的代理,银行账户则是一大捆现金的代理。 它们都实现了同样的接口,均可用于进行支付。消费者会非常满意,因为不必随身携带大量现金;商店老板同样会十分高兴,因为交易收入能以电子化的方式进入商店的银行账户中,无需担心存款时出现现金丢失或被抢劫的情况。

实现方式

1、静态代理

案例实现步骤

(1)创建一个接口,定义卖u盘的方法。

public interface UsbSell {
 // 厂家和商家都要实现的功能(卖U盘)
    float sell(int amount);
}

(2)创建工厂类

// 厂家不接受用户的单独购买,需要商家代理销售
public class UsbFactory implements UsbSell {

    @Override
    public float sell(int amount) {
        return 85.0f * amount;  // 出厂价
    }
}

(3)创建商家类(代理类)

public class TaoBao implements UsbSell {
    // 声明商家代理的具体是哪个厂家
    private UsbSell factory = new UsbFactory();

    @Override
    public float sell(int amount) {
        float price = factory.sell(amount);
        float finalPrice = price + 25; // 功能增强
        System.out.println("某宝返还您5元优惠券!!!");
        return finalPrice;  // 售价
    }
}

 改价格操作是不能被消费者访问和使用的,作用对象只能是商家(微商、实体商店等)。

(4)创建测试类(普通消费者)

public class shopMain {
    public static void main(String[] args) {
        TaoBao tb = new TaoBao();
        float pay = tb.sell(3);
        System.out.println("您购买的U盘,淘宝售价: "+ pay + '元');
    }
}

输出结果:

3x 85+25 = 280,验算后无误。

缺点

  • 当目标类增多了,代理类也需要增加(例如:上例中创建了一个工厂类,那么该类只能代表一个品牌工厂,当建立了其它品牌的工厂后,还需要为该工厂创建代理类)。
  • 当接口的方法增加或修改的时候,很多类都需要修改。

(2)动态代理

含义:​ 依靠jdk的反射机制,创建对象的能力,创建的是代理类的对象,不需要我们创建代理类。

动态代理会在jdk运行期间,动态创建class字节码并加载到JVM内存中。实现方式常用的有两种:使用JDK代理,与通过CGLlB动态代理。

JDK代理实现

这部分需理解 java反射包中的类和接口实现动态代理的功能,反射包java.lang.reflect里有三个类:InvocationHandler、Method、Proxy。

  • InvocationHandler接口:表示代理要干什么(定义目标类要完成的功能)。
  • method:目标类中的方法,jdk负责提供method对象。
  • proxy:使用Proxy类的静态方法,来创建代理对象,并把返回值转换为接口类型。

(1)创建接口

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

(2)创建工厂类(目标类)

public class UsbFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        return 85.0f * amount;  // 出厂价
    }
}

 (3)创建InvocationHandler接口的实现类

//必须实现InvocationHandler接口,完成代理类的功能(调用目标方法、功能增强)
public class MySellHandler implements InvocationHandler {
    private  Object target = null;
    //动态代理的目标对象是动态传入的,传谁就给谁创建代理
    public MySellHandler(Object target){
        this.target = target;
    }
    //args代表接口中sell方法的参数
    @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("某宝返还您5元优惠券!!!");
        return res;
    }
}

(4)编写测试类

public class Test {
    public static void main(String[] args) {
        //创建目标对象
        UsbSell usbFactory = new UsbFactory();
        //创建invocationHandler对象
        InvocationHandler invocationHandler = new MySellHandler(usbFactory);
        //创建代理对象
        UsbSell proxy= (UsbSell) Proxy.newProxyInstance(
                usbFactory.getClass().getClassLoader(),
                usbFactory.getClass().getInterfaces(),
                invocationHandler
        );
        System.out.println("您购买的U盘,淘宝售价:"+ proxy.sell(100) + '元');
    }
}

输出结果:

与静态代理不同的是,我们不再需要每个工厂的具体实现类(如TaoBao.java) 。添加方法时,只需修改接口和目标类两个文件,客户类(Test.java)使用Proxy对象调用即可。注意jdk的动态代理必须有接口,目标类一定要实现该接口。

参考:设计模式(代理模式) |  代理设计模式

标签:java,对象,创建,代理,模式,UsbSell,接口,public
来源: https://blog.csdn.net/weixin_45719444/article/details/122731624

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有