Java设计模式之结构型-装饰器模式(UML类图+案例分析)

news2024/12/26 20:53:59

目录

一、基本概念

二、角色设计

三、代码实现

案例一

案例二 

四、总结 


一、基本概念

装饰器模式是指不必在改变原有的类和不使用继承的情况下,动态扩展一个对象的功能。

二、角色设计

c3307e6d567d41ea9403f8464b53c330.png

角色描述
抽象构件是一个接口或者抽象类,定义我们最核心的对象
基础构件抽象构件的实现,可以单独用,也可以将其进行装饰
装饰角色一般是一个抽象类,继承自或实现抽象构件,在它的属性中有个变量指向抽象构建,这是关键
具体装饰角色Type-C充电和Wireless充电是两个具体的装饰类,可以把基础构件进行装饰,延伸出新的功能

三、代码实现

案例一

假设一个场景,以前手机充电只有usb充电,但是目前手机多出了2种新的充电方式,Typc-C和无线充电,这就需要我们动态去扩展功能,让我们看看装饰器如何实现的。

1、首先定义一个基本的充电接口,采用usb充电

public interface Charge {
    
    public void usb();
    
}

2、实现一个普通手机去使用usb接口充电

public class PhoneCharge implements Charge{

    @Override
    public void usb() {
        System.out.println("采用usb接口充电...");
    }
    
}

3、 抽象的充电装饰器

public abstract class AbstractPhoneDecorator implements Charge{

    protected final Charge charge;

    public AbstractPhoneDecorator(Charge charge){
        this.charge = charge;
    }

}

4、Type-C充电具体装饰

public class TypeCDecorator extends AbstractPhoneDecorator{


    public TypeCDecorator(Charge charge) {
        super(charge);
    }

    @Override
    public void usb() {
        super.charge.usb();
        System.out.println("采用type-c接口充电...");
    }

}

5、无线充电的具体装饰

public class WirelessDecorator extends AbstractPhoneDecorator{

    public WirelessDecorator(Charge charge) {
        super(charge);
    }

    @Override
    public void usb() {
        super.charge.usb();
        System.out.println("采用无线充电...");
    }
    
}

6、测试类

    public static void main(String[] args) {
        
        Charge charge = new PhoneCharge();
        TypeCDecorator typeCDecorator = new TypeCDecorator(charge);
        WirelessDecorator wirelessDecorator = new WirelessDecorator(typeCDecorator);
        wirelessDecorator.usb();
        
    }

7、运行结果

案例二 

现在假设有一个新的场景,在我们平时网上购买一个商品可以不光使用红包抵扣,同时也有满减优惠,案例二假设一个用户在网上买了10个单价为15元的牙杯,他现在有一个20元的红包和50元的抵扣券,下面通过代码来进行简单的模拟实现。

1、创建订单实体类

import java.math.BigDecimal;

/**
 * 订单类
 * @author HTT
 */
public class Order {

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getGoodsInfo() {
        return goodsInfo;
    }

    public void setGoodsInfo(String goodsInfo) {
        this.goodsInfo = goodsInfo;
    }

    public BigDecimal getGoodsPrice() {
        return goodsPrice;
    }

    public void setGoodsPrice(BigDecimal goodsPrice) {
        this.goodsPrice = goodsPrice;
    }

    public BigDecimal getGoodsCount() {
        return goodsCount;
    }

    public void setGoodsCount(BigDecimal goodsCount) {
        this.goodsCount = goodsCount;
    }

    public Coupon getFullReduction() {
        return fullReduction;
    }

    public void setFullReduction(Coupon couponInfo) {
        this.fullReduction = couponInfo;
    }

    public Coupon getRedPacketInfo() {
        return redPacketInfo;
    }

    public void setRedPacketInfo(Coupon redPacketInfo) {
        this.redPacketInfo = redPacketInfo;
    }

    public BigDecimal getGoodsAmount() {
        return goodsAmount;
    }

    public void setGoodsAmount(BigDecimal goodsAmount) {
        this.goodsAmount = goodsAmount;
    }

    /**
     * 订单id
     */
    private String id;

    /**
     * 商品信息
     */
    private String goodsInfo;

    /**
     * 商品价格
     */
    private BigDecimal goodsPrice;

    /**
     * 商品信息
     */
    private BigDecimal goodsCount;

    /**
     * 商品总价
     */
    private BigDecimal goodsAmount;

    /**
     * 满减信息
     */
    private Coupon fullReduction;
    /**
     * 红包信息
     */
    private Coupon redPacketInfo;
}

2、创建优惠券实体类

import java.math.BigDecimal;

/**
 * 优惠信息
 * @author HTT
 */
public class Coupon {

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public BigDecimal getCouponPrice() {
        return couponPrice;
    }

    public void setCouponPrice(BigDecimal couponPrice) {
        this.couponPrice = couponPrice;
    }


    public String getCouponType() {
        return couponType;
    }

    public void setCouponType(String couponType) {
        this.couponType = couponType;
    }

    private int id;

    /**
     * 优惠金额
     */
    private BigDecimal couponPrice;

    /**
     * 优惠券类型
     */
    private String couponType;

}

 3、创建一个抽象构建,是所有订单的基本需求,用于计算订单的总额

/**
 * 抽象构建 用于计算订单总金额
 * @author HTT
 */
public interface OrderDecorator {

    public BigDecimal calculateOrderPrice(Order order);
    
}

4、 抽象构建的基础实现类

/**
 * 基础构建实现类 计算订单金额
 * @author HTT
 */
public class BaseOrder implements OrderDecorator{

    @Override
    public BigDecimal calculateOrderPrice(Order order) {
        return order.getGoodsPrice().multiply(order.getGoodsCount());
    }

}

5、订单的抽象装饰器 

/**
 * 抽象的订单装饰器
 * @author HTT
 */
public abstract class BaseOrderDecorator implements OrderDecorator{

    private OrderDecorator orderDecorator;

    public BaseOrderDecorator(OrderDecorator orderDecorator){
        this.orderDecorator = orderDecorator;
    }

    @Override
    public BigDecimal calculateOrderPrice(Order order) {
        return orderDecorator.calculateOrderPrice(order);
    }

}

6、红包装饰器

/**
 * 红包装饰器
 * @author HTT
 */
public class RedPacketDecorator extends BaseOrderDecorator{

    public RedPacketDecorator(OrderDecorator orderDecorator) {
        super(orderDecorator);
    }

    @Override
    public BigDecimal calculateOrderPrice(Order order) {
        order.setGoodsAmount(super.calculateOrderPrice(order));
        return calculateRedPacketPrice(order);
    }

    private BigDecimal calculateRedPacketPrice(Order order){
        return order.getGoodsAmount().subtract(order.getRedPacketInfo().getCouponPrice());
    }
}

7、满减装饰器

/**
 * 满减装饰器
 * @author HTT
 */
public class FullReductionDecorator extends BaseOrderDecorator{

    public FullReductionDecorator(OrderDecorator orderDecorator) {
        super(orderDecorator);
    }

    @Override
    public BigDecimal calculateOrderPrice(Order order) {
        order.setGoodsAmount(super.calculateOrderPrice(order));
        return calculateRedPacketPrice(order);
    }

    private BigDecimal calculateRedPacketPrice(Order order){
        return order.getGoodsAmount().subtract(order.getFullReduction().getCouponPrice());
    }
}

 8、测试

public static void main(String[] args) {
        //初始化红包信息
        Coupon redPacket = new Coupon();
        redPacket.setId(1);
        redPacket.setCouponType("红包");
        redPacket.setCouponPrice(new BigDecimal("20"));
        //初始化满减信息
        Coupon fullReduction = new Coupon();
        fullReduction.setId(2);
        fullReduction.setCouponType("满减");
        fullReduction.setCouponPrice(new BigDecimal("50"));

        //初始化订单信息
        Order order = new Order();
        order.setId(UUID.randomUUID().toString());
        order.setGoodsInfo("牙杯");
        order.setGoodsPrice(new BigDecimal("15"));
        order.setGoodsCount(new BigDecimal("10"));
        order.setRedPacketInfo(redPacket);
        order.setFullReduction(fullReduction);

        OrderDecorator orderDecorator = new BaseOrder();
        BaseOrderDecorator redPacketDecorator = new RedPacketDecorator(orderDecorator);
        BaseOrderDecorator fullReductionDecorator = new FullReductionDecorator(redPacketDecorator);
        System.out.println(fullReductionDecorator.calculateOrderPrice(order));

    }

 9、运行结果 

四、总结 

优点:装饰类和被装饰类可以独立发展,降低了耦合,可以动态去扩展一个实现类的功能

缺点:装饰器模式会增加许多的子类,会使代码繁多增加程序复杂性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/682914.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科技云报道:边缘计算步入“黄金年代”

科技云报道原创。 当前时点,AI大模型已经站在了从“玩具”向“工具”快速演化的关键迭代期。如何让大模型渗透进入各类垂直场景,如何更低成本的使用大模型,如何让更多场景与用户接触AI,成为了发展的下一个重点。 在AI向实际场景…

大数据应用——总结与反思

1.谈谈你对大数据行业的认识,目前对应的大数据岗位有哪些?每种岗位需要掌握哪些技能水平?目前自己的差距在哪里? (1)概述 对于大数据行业的认识,我的理解是,大数据是指海量数据&…

8种常见的SQL错误用法

前言:MySQL在2016年仍然保持强劲的数据库流行度增长趋势。越来越多的客户将自己的应用建立在MySQL数据库之上,甚至是从Oracle迁移到MySQL上来。但也存在部分客户在使用MySQL数据库的过程中遇到一些比如响应时间慢,CPU打满等情况。现将《Apsar…

Dumuz同步微信通讯录及常见问题

在Dumuz工具中,【微信通讯录同步】主要功能是从当前登录的微信上下载通讯录相关成员数据。 第1步: 打开应用【微信-消息批量发送】,在工具栏中点击【微信通讯录】如下图所示: 第2步: 进入【微信通讯录】 对话框&#…

【AUTOSAR】AUTOSAR开发工具链(九)----基于BTC的MIL/SIL测试操作说明(1)

一、BTC使用注意事项 1、安装成功后,在Edit->Preference->General->Compiler可以找到编辑器MSVC140 启动BTC:插入电子狗、选择与电子狗相匹配的License、选择相应的工具包 B2B就是MIL V SIL 适用于MBD开发的测试,单独SIL适用于手写…

【Jmeter教程】__将提取的参数并设置成全局变量(常用于提取token)

目录 一、提取参数 1、使用正则表达式提取器提取token 2、使用json提取器提取token 二、将提取参数设置成全局变量 三、常见问题 一、提取参数 1、使用正则表达式提取器提取token 查看登录响应参数找出token。图中token为 "ticketString": "ccf26b17-a96f…

深入理解MySQL主从配置原理

目录 1. MySQL主从复制原理工作原理 2. 主从配置步骤1: 配置主节点2: 备份主节点数据3: 配置从节点4: 启动主从复制 3.常见问题4. 需要考虑的一些因素 MySQL主从复制是一种数据库复制技术,通过将一个MySQL服务器(主节点)上的数据同步到其他My…

IP地点定位为什么有误差?

随着互联网的不断普及,人们对IP地点定位需求越来越多。然而,即便是在现代技术的支持下IP地点定位仍然存在误差。那么,IP地点定位为什么会出现误差呢? IP(Internet Protocol)地址是指互联网协议(…

SpringCloudSpringcloudAlibaba

SpringCloud 一:微服务架构1.1 ESB1.2 微服务与微服务 二 :编写SpringCloud代码2.1 父模块SpringCloudDemo项目2.2 公共类模块SpringCloud-api项目2.3 消费模块SpringCloud-user-8001项目2.4 RestTemplate 三:注册中心:Eureka3.1 …

机器学习——Kmeans算法

一、实验目的 学习sklearn模块中的KMeans算法 二、实验内容 学习KMeans算法,了解模型创建、使用模型及模型评价等操作 三、实验原理或流程 实验原理: K-means算法是将样本聚类成k个簇(cluster),具体算法描述如下: 1、随机选取k个聚类质…

春招上岸阿里,好多问题当场尬住!

一个粉丝,23年应届毕业生, 双非本科。最近他校招上岸了,拿到了阿里软件测试岗位的Offer。 他总结了一下面试题,感觉很多内容还是有难度的,尤其是对于应届生来说。下面是他整理的面试题,看看这种校招面试难…

sonarqube本地安装使用

sonarqube本地安装使用 sonarqube本地安装使用配置 官网网址:https://www.sonarqube.org/ 注意:sonarqube版本需要与jdk和数据库版本相对应,以及sonarqube对应电脑的位数 本案例中:JDK8、sonarqube7.6版本 在说明文档中可以…

svg图版绘制

推荐工具:Inkscape 绘制带折线的图版,使用左侧工具栏(绘制贝塞尔曲线和直线) 选中顶部(创建一个直线段构成的折线) 直接使用鼠标左键点对点进行绘制,停顿一次为一个坐标,鼠标右击…

软件测试技能,JMeter压力测试教程,setUp线程组实现用户先登录(八)

前言 在接口测试的时候,很多接口都需要用户先登录,才有访问接口的权限。在测试的时候,我们的关注点其实是当前测试的接口,登录只是一个前置操作 像 python 的 unittest 和 pytest 框架都有 setUp 的概念,前置操作用来…

探究物流机器人产业新发展

原创 | 文 BFT机器人 01 我国物流机器人发展现状 机器人人工智能加速了物流行业的发展,优化和提高了物流资源、物流流程和物流效率。 近年来,机器人相关产品和服务得到了快速推广,并经常应用于不同的存储和物流场景,如电子商务存储…

InternalAuthenticationServiceException: Invalid bound statement (not found):

InternalAuthenticationServiceException: Invalid bound statement (not found): 在项目中,我们会遇到如下问题,但是这个问题是一种常见的典型问题 org.springframework.security.authentication.InternalAuthenticationServiceException: Invalid boun…

SciencePub学术 | 纳米技术类重点SCIEEI征稿中

SciencePub学术 刊源推荐: 纳米技术类重点SCI&EI征稿中!1区正刊,进展顺利、录用快。信息如下,录满为止: 一、期刊概况: 纳米技术类重点SCI&EI 📌【期刊简介】IF:6.0-6.5,…

亚马逊云科技数据库市场份额提升迅速,合作伙伴和开发者生态系统为其赋能

对比常规的基础设施上云和应用上云,企业对于数据上云一直保持最为慎重的态度。不过也不是一成不变的,Gartner前不久公布的一组数据显示,在2022年全球数据库管理系统的市场份额排名中,作为纯云厂商的亚马逊云科技,超越了老牌传统数据库厂商甲骨文和微软,首次位居第一。 降低企业…

软件测试技能,JMeter压力测试教程,压测带token的接口(六)

目录 前言 一、场景案例 二、测试token准备 三、jmeter CSV数据文件设置 四、运行结果 前言 工作中我们需要压测的接口大部分都是需要先登陆后,带着token的接口(或者带着cookies),我们可以先登陆获取token再关联到下个接口 …

如何使用 ChatGPT 赚钱(10 种简单的方法)

即使自从OpenAI推出ChatGPT以来,科技领域的情况也发生了巨大变化。OpenAI 大型语言模型 (LLM) 非常强大,它可以做很多事情,包括写论文、数字运算、代码编写等创造性工作。人们现在正在使用ChatGPT疯狂的AI功能来赚钱。…