设为首页 加入收藏

TOP

quarkus依赖注入之八:装饰器(Decorator)(一)
2023-08-26 21:11:24 】 浏览:71
Tags:quarkus 赖注入 Decorator

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本篇是《quarkus依赖注入》系列的第八篇,目标是掌握quarkus实现的一个CDI特性:装饰器(Decorator)
  • 提到装饰器,熟悉设计模式的读者应该会想到装饰器模式,个人觉得下面这幅图很好的解释了装饰器模式,左下角的红框是关键点:自己的send方法中,先调用父类的send(也就是被装饰类的send),然后才是自己的业务逻辑
54
  • quarkus也支持装饰器模式,通过注解DecoratorDelegate实现,今天咱们就通过实战掌握如何在quarks框架下通过装饰器扩展应用
  • quarkus是按照CDI的标准来支持装饰器模式的,下图来自官方文档

image-20220409210857612

  • 接下来进入实战环节

实战功能说明

  • 网上讲述装饰器模式的文章中,有个咖啡价格的例子非常经典,如下图所示:
  1. 一杯意式浓缩咖啡(Espresso)价格3美元
  2. 拿铁(Latte)由意式浓缩+牛奶组成,价格是意式浓缩和牛奶之和,即5美元
  3. 焦糖玛奇朵(CaramelMacchiato)由拿铁+焦糖组成,价格比拿铁多了焦糖的1美元,即6美元
  4. 每种咖啡都是一种对象,价格由getPrice方法返回
流程图 - 2022-04-09T165959.292
  • 在上述场景中,当咖啡的内容不断丰富,咖啡价格也要做相应调整,装饰器的作用是让代码优雅的应对变化,对内代码整洁低耦合,对外保持统一接口getPrice

  • 装饰器模式本身并不是本篇的重点,咱们还是聚焦quarkus下的装饰器功能:在咖啡价格的基础上,通过装饰器计算出拿铁的价格

  • 接下来开始编码

编码实战

  • 首先定义接口Coffee.java,不论是意式浓缩、拿铁、还是其他种类,对外都称之为Coffee,都有getPrice方法
package com.bolingcavalry.decorator;

public interface Coffee {

    /**
     * 咖啡名称
     * @return
     */
    String name();

    /**
     * 当前咖啡的价格
     * @return
     */
    int getPrice();
}
  • 然后是最基础的意式浓缩咖啡,非常简单的一个bean,定价3美元,这里有个细节要注意:name方法中写死了字符串Espresso,而没用getClass().getSimpleName(),这是因为在quarkus容器中,Espresso的bean并非Espresso类型,而是动态生成的代理类,所以getClass返回的类不是Espresso
package com.bolingcavalry.decorator.impl;

import com.bolingcavalry.decorator.Coffee;

import javax.enterprise.context.ApplicationScoped;

/**
 * 意式浓缩咖啡,价格3美元
 */
@ApplicationScoped
public class Espresso implements Coffee {

    @Override
    public String name() {
        return "Espresso";
    }

    @Override
    public int getPrice() {
        return 3;
    }
}
  • 接下来就是重点了,拿铁,由意式浓缩+牛奶组成,代码如下,有几处要注意的地方稍后会提到
package com.bolingcavalry.decorator.impl;

import com.bolingcavalry.decorator.Coffee;
import io.quarkus.arc.Priority;
import io.quarkus.logging.Log;

import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;

@Decorator
@Priority(11)
public class Latte implements Coffee {
    /**
     * 牛奶价格:2美元
     */
    private static final int MILK_PRICE = 2;

    @Delegate
    @Inject
    Coffee delegate;

    @Override
    public String name() {
        return "Latte";
    }

    @Override
    public int getPrice() {
        // 将Latte的代理类打印出来,看quarkus注入的是否正确
        Log.info("Latte's delegate type : " + this.delegate.name());
        return delegate.getPrice() + MILK_PRICE;
    }
}
  • 上述代码有以下几处要注意
  1. 先明确目的:我们设计Latte这个bean,本意是通过装饰器模式来装饰Espresso,因此才会用到quarkus的装饰器功能
  2. 使用quarkus的装饰器功能时,有两件事必须要做:装饰类要用注解Decorator修饰,被装饰类要用注解Delegate修饰
  3. 因此,Latte被注解Decorator修饰,Latte的成员变量delegate是被装饰类,要用注解Delegate修饰,
  4. Latte的成员变量delegate并未指明是Espresso,quarkus会选择Espresso的bean注入到这里
  5. 在getPrice方法中打印出delegate.name方法的返回值,验证delegate的身份,以确认quarkus注入的是否正确
  6. 注解Priority很重要,留在接下来的CaramelMacchiato类(焦糖玛奇朵)写完后再说清楚
  • 接下来是CaramelMacchiato类(焦糖玛奇朵),有几处要注意的地方稍后会说明
package com.bolingcavalry.decorator.impl;

import com.bolingcavalry.decorator.Coffee;
import io.quarkus.arc.Priority;
import io.quarkus.logging.Log;

import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;

/**
 * 焦糖玛奇朵:拿铁+焦糖
 */
@Decorator
@Priority(10)
public class CaramelMacchiato implements Coffee {

    /**
     * 焦糖价格:1美元
     */
    private static final int CARAMEL_PRICE = 1;

    @Delegate
    @Inject
    Coffee delegate;

    @Override
    public String name() {
        return "CaramelMacchiato";
    }

    @Ov
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇quarkus依赖注入之九:bean读写锁 下一篇Java后端05(初识MyBatis)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目