【Java设计模式】抽象文档模式:以灵活性简化数据处理

news2024/9/26 5:19:32

文章目录

    • 抽象文档设计模式的意图
    • 抽象文档模式的详细解释及实际示例
    • Java中抽象文档模式的编程示例
    • 抽象文档模式类图
    • Java中何时使用抽象文档模式
    • 抽象文档模式的优点和权衡
    • 源码下载
    • 参考和致谢

抽象文档设计模式的意图

Java中的抽象文档设计模式是一种关键的结构设计模式,它通过为各种文档类型定义一个通用接口,提供了一种处理层次结构和树状数据结构的一致方法。它将核心文档结构与特定的数据格式分离,实现动态更新并简化维护。

抽象文档模式的详细解释及实际示例

Java中的抽象文档设计模式允许动态处理非静态属性。此模式使用特征的概念来实现类型安全,并将不同类的属性分离到一组接口中。
实际示例

考虑一个在Java中实现抽象文档设计模式的图书馆系统,其中书籍可以有不同的格式和属性:实体书、电子书和有声书。每种格式都有独特的属性,例如实体书的页数、电子书的文件大小和有声书的时长。抽象文档设计模式允许图书馆系统灵活地管理这些不同的格式。通过使用此模式,系统可以动态地存储和检索属性,而不需要为每种书籍类型设置严格的结构,使得在未来添加新格式或属性时无需对代码库进行重大更改。
通俗地说
抽象文档模式允许在对象上附加属性而无需对象知晓。
维基百科说
一种面向对象的结构设计模式,用于在松散类型的键值存储中组织对象,并使用类型化视图公开数据。该模式的目的是在强类型语言中的组件之间实现高度的灵活性,其中可以动态地向对象树添加新属性,同时不会失去类型安全的支持。该模式利用特征将类的不同属性分离到不同的接口中。

Java中抽象文档模式的编程示例

考虑一辆由多个部分组成的汽车。然而,我们不知道特定的汽车是否真的拥有所有的部件,或者只有其中一些。我们的汽车是动态的且极其灵活。
首先定义基类DocumentAbstractDocument。它们基本上使对象持有一个属性映射和任意数量的子对象。

public interface Document {
    Void put(String key, Object value);
    Object get(String key);
    <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);
}
public abstract class AbstractDocument implements Document {
    private final Map<String, Object> properties;
    protected AbstractDocument(Map<String, Object> properties) {
        Objects.requireNonNull(properties, "properties map is required");
        this.properties = properties;
    }
    @Override
    public Void put(String key, Object value) {
        properties.put(key, value);
        return null;
    }
    @Override
    public Object get(String key) {
        return properties.get(key);
    }
    @Override
    public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {
        return Stream.ofNullable(get(key))
               .filter(Objects::nonNull)
               .map(el -> (List<Map<String, Object>>) el)
               .findAny()
               .stream()
               .flatMap(Collection::stream)
               .map(constructor);
    }
    
    // 其他属性和方法...
}

接下来定义一个枚举Property和一组接口用于类型、价格、型号和部件。这允许我们为Car类创建看起来静态的接口。

public enum Property {
    PARTS, TYPE, PRICE, MODEL
}
public interface HasType extends Document {
    default Optional<String> getType() {
        return Optional.ofNullable((String) get(Property.TYPE.toString()));
    }
}
public interface HasPrice extends Document {
    default Optional<Number> getPrice() {
        return Optional.ofNullable((Number) get(Property.PRICE.toString()));
    }
}
public interface HasModel extends Document {
    default Optional<String> getModel() {
        return Optional.ofNullable((String) get(Property.MODEL.toString()));
    }
}
public interface HasParts extends Document {
    default Stream<Part> getParts() {
        return children(Property.PARTS.toString(), Part::new);
    }
}

现在我们准备引入Car

public class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {
    public Car(Map<String, Object> properties) {
        super(properties);
    }
}

最后,这是我们在一个完整示例中构建和使用Car的方式。

  public static void main(String[] args) {
    LOGGER.info("Constructing parts and car");
    var wheelProperties = Map.of(
            Property.TYPE.toString(), "wheel",
            Property.MODEL.toString(), "15C",
            Property.PRICE.toString(), 100L);
    var doorProperties = Map.of(
            Property.TYPE.toString(), "door",
            Property.MODEL.toString(), "Lambo",
            Property.PRICE.toString(), 300L);
    var carProperties = Map.of(
            Property.MODEL.toString(), "300SL",
            Property.PRICE.toString(), 10000L,
            Property.PARTS.toString(), List.of(wheelProperties, doorProperties));
    var car = new Car(carProperties);
    LOGGER.info("Here is our car:");
    LOGGER.info("-> model: {}", car.getModel().orElseThrow());
    LOGGER.info("-> price: {}", car.getPrice().orElseThrow());
    LOGGER.info("-> parts: ");
    car.getParts().forEach(p -> LOGGER.info("\t{}/{}/{}",
            p.getType().orElse(null),
            p.getModel().orElse(null),
            p.getPrice().orElse(null))
    );
}

程序输出:

07:21:57.391 [main] INFO com.iluwatar.abstractdocument.App -- Constructing parts and car
07:21:57.393 [main] INFO com.iluwatar.abstractdocument.App -- Here is our car:
07:21:57.393 [main] INFO com.iluwatar.abstractdocument.App -- -> model: 300SL
07:21:57.394 [main] INFO com.iluwatar.abstractdocument.App -- -> price: 10000
07:21:57.394 [main] INFO com.iluwatar.abstractdocument.App -- -> parts: 
07:21:57.395 [main] INFO com.iluwatar.abstractdocument.App -- 	wheel/15C/100
07:21:57.395 [main] INFO com.iluwatar.abstractdocument.App -- 	door/Lambo/300

抽象文档模式类图

在这里插入图片描述

Java中何时使用抽象文档模式

抽象文档设计模式在需要管理具有一些共同属性或行为但也具有特定于其各自类型的独特属性或行为的不同文档类型的场景中特别有用。以下是一些可以应用抽象文档设计模式的场景:

  • 内容管理系统(CMS):在 CMS 中,可能有各种类型的内容,如文章、图像、视频等。每种类型的内容可能具有共享属性,如创建日期、作者和标签,同时也具有特定于图像的图像尺寸或视频的视频时长等特定属性。
  • 文件系统:如果正在设计一个需要管理不同类型文件的文件系统,如文档、图像、音频文件和目录,抽象文档模式可以帮助提供一种一致的方式来访问属性,如文件大小、创建日期等,同时允许特定属性,如图像分辨率或音频时长。
  • 电子商务系统:电子商务平台可能有不同的产品类型,如实体产品、数字下载和订阅。每种类型可以共享通用属性,如名称、价格和描述,同时具有实体产品的运输重量或数字产品的下载链接等独特属性。
  • 医疗记录系统:在医疗保健中,患者记录可能包括各种类型的数据,如人口统计信息、医疗历史、测试结果和处方。抽象文档模式可以帮助管理共享属性,如患者 ID 和出生日期,同时适应特定属性,如测试结果或处方药物。
  • 配置管理:在处理软件应用程序的配置设置时,可能有不同类型的配置元素,每个元素都有自己的一组属性。抽象文档模式可用于管理这些配置元素,同时确保有一种一致的方式来访问和操作它们的属性。
  • 教育平台:教育系统可能有各种类型的学习材料,如基于文本的内容、视频、测验和作业。可以共享诸如标题、作者和发布日期等常见属性,而独特属性,如视频时长或作业截止日期,可以特定于每种类型。
  • 项目管理工具:在项目管理应用程序中,可以有不同类型的任务,如待办事项、里程碑和问题。抽象文档模式可用于处理一般属性,如任务名称和负责人,同时允许特定属性,如里程碑日期或问题优先级。
  • 文档具有多样化和不断演变的属性结构。
  • 动态添加新属性是常见需求。
  • 从特定格式解耦数据访问至关重要。
  • 代码的可维护性和灵活性至关重要。
    抽象文档设计模式背后的关键思想是提供一种灵活且可扩展的方式来管理具有共享和不同属性的不同类型的文档或实体。通过定义一个通用接口并在各种文档类型中实现它,可以实现一种更有条理和一致的方法来处理复杂的数据结构。

抽象文档模式的优点和权衡

优点:

  • 灵活性:适应各种文档结构和属性。
  • 可扩展性:动态添加新属性而不破坏现有代码。
  • 可维护性:由于关注点分离,促进了干净且适应性强的代码。
  • 可重用性:类型化视图实现了对特定属性类型的代码重用。
    权衡:
  • 复杂性:需要定义接口和视图,增加了实现的开销。
  • 性能:与直接数据访问相比,可能会引入轻微的性能开销。

源码下载

https://download.csdn.net/download/weixin_42545951/89677160

参考和致谢

  • 设计模式:可复用的面向对象软件元素
  • Java设计模式:具有实际示例的实践经验
  • 面向模式的软件体系结构卷4:分布式计算的模式语言(第4卷)
  • 企业应用架构模式
  • 抽象文档模式(维基百科)
  • 处理属性(Martin Fowler)

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

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

相关文章

【mysql集群之组复制】

目录 一、 mysql高可用之组复制 (MGR)组复制单主和多主模式实现mysql的组复制 二、 mysql-router&#xff08;mysql路由&#xff09;实现负载均衡 一、 mysql高可用之组复制 (MGR) MySQL Group Replication(简称 MGR )是 MySQL 官方于 2016 年 12 月推出的一个全新的高可用与高…

OpenHarmony南向开发:SmartPerf-Device使用说明

简介 SmartPerf 端是一款基于 OpenHarmony 系统开发的性能功耗测试工具&#xff0c;操作简单易用&#xff0c;可提供包括性能、功耗的关键 KPI 指标&#xff0c;给出具体指标的测试值&#xff0c;包括采集设备的 FPS、CPU、GPU、Ftrace 等指标数据&#xff1b; 目前 SmartPer…

uniapp之app版本更新,整体更新和热更新

目录 需求&#xff1a; 版本更新有两种更新模式&#xff1a; 实现&#xff1a; 前提&#xff1a; 热更新&#xff1a; 打包wgt包&#xff1a;菜单->发行->原生App-制作移动App资源升级包 代码逻辑: 整体更新&#xff1a; 实际项目开发&#xff1a; 需求&#xf…

Linux网络编程——C/C++Web服务器(二):IO多路复用select/poll/epoll实现服务器监听多客户端事件

环境配置&#xff1a;windows电脑用户可以安装WSL配置Linux环境&#xff0c;并且安装vscode及wsl的插件通过vscode连接本机电脑的Linux。 前置内容&#xff1a; Linux网络编程——C/CWeb服务器&#xff08;一&#xff09;&#xff1a;不断创建新线程处理多客户端连接和通信-C…

代码随想录算法训练营第二十七天(贪心 一)

硬拖拖到现在才写完。。。 关于贪心: 文章链接: 代码随想录 文章摘要: 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 贪心算法并没有固定的套路。 和其他算法不同&#xff0c;贪心没有能看出局部最优是否能推出整体最优的通法。 用来验证可不可以…

软件渗透测试必要性简析,第三方软件测试机构如何进行渗透测试?

在信息技术迅速发展的今天&#xff0c;软件渗透测试逐渐成为了确保信息安全的重要环节。软件渗透测试指的是对系统或应用程序进行模拟攻击&#xff0c;以发现其潜在的安全风险与脆弱性。不同于传统的安全审计&#xff0c;渗透测试更注重实际攻击过程和攻击者的视角&#xff0c;…

IO进程线程8月26ri

1&#xff0c;思维导图 2&#xff0c;用两个进程分别复制文件的上下两部分到另一个文件 #include<myhead.h> int main(int argc, const char *argv[]) {int fpopen("./1.txt",O_RDONLY);if(fp-1){perror("open");return -1;}int countlseek(fp,0,SE…

如何在 mind+ 中编写 python 程序

打开Mind&#xff0c;点击窗口右上角的【Python模式】按钮&#xff0c;由实时模式切换到Python模式。 将默认的循环执行模块拖动到左边的模块区删除。 点击【变量】&#xff0c;将【打印【Hello World】】模块拼接到【Python主程序开始】下方。 将【获取输入&#xff0c;提示语…

redis(未授权访问漏洞)

环境准备 下载并安装Redis 首先&#xff0c;下载Redis的源代码包并解压&#xff1a; wget http://download.redis.io/releases/redis-2.8.17.tar.gz tar xzf redis-2.8.17.tar.gz cd redis-2.8.17接着&#xff0c;编译安装Redis&#xff1a; 编译完成后&#xff0c;进入src目录…

自动化任务工具 | zTasker v1.97.1 绿色版

在自动化任务管理领域&#xff0c;一款名为zTasker的软件以其卓越的性能和易用性脱颖而出。今天&#xff0c;电脑天空将为大家详细介绍这款软件的亮点和使用场景。 功能特点 1. 轻量级设计&#xff0c;快速启动 zTasker以其小巧的体积和快速的启动速度&#xff0c;为用户提供…

模型 7S分析法(麦肯锡)

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。组织全面诊断&#xff0c;战略协同优化。 1 7S分析法(麦肯锡)的应用 1.1 邮储银行的转型&#xff1a;基于麦肯锡7S模型的竞争力提升 中国邮储银行面临着激烈的金融行业竞争&#xff0c;为了迅速提升…

考研数学 高等数学----导数应用

核心框架 前置知识 正式内容 知识点1: 知识点2: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知识点: 知…

嵌入式系统课后习题(带答案)

资料截图&#xff08;部分&#xff09;&#xff1a; &#x1f680; 获取更多详细资料可点击链接进群领取&#xff0c;谢谢支持&#x1f447; 点击免费领取更多资料

Ant Design Vue中Modal.confirm无法自动关闭

温馨tips:着急看解决方法可跳过碎碎念~ 前两天经理扔给我一个问题&#xff1a;“这个弹窗怎么关不上了&#xff1f;” 我怀着无所谓的心态&#xff1a;小意思啦&#xff0c;5分钟之内解决完~ …当然flag是不能随便乱立的 拉下来项目&#xff08;原神启动&#xff08;不是&…

@ohos.systemParameterEnhance系统参数接口调用:获取系统属性

在去年的文章&#xff0c;笔者介绍了如何使用修改修改OpenHarmony 设备厂家名称 、硬件版本号 等系统属性&#xff0c;本文介绍一下在应用层怎么获取系统属性。 开发环境 DAYU200 rk3568开发板OpenHarmony 4.1r API 10 (full sdk)DevEco Studio 4.1 Release 开发步骤 1.首先…

浅谈【数据结构】树与二叉树之哈夫曼树

目录 1、哈夫曼树 1.1哈夫曼编码 1.2哈夫曼树 1.3构建一棵哈夫曼树 谢谢帅气美丽且优秀的你看完我的文章还要点赞、收藏加关注 没错&#xff0c;说的就是你&#xff0c;不用再怀疑&#xff01;&#xff01;&#xff01; 希望我的文章内容能对你有帮助&#xff0c;一起努力吧…

【FPGA数字信号处理】什么是信号?

在数字信号处理的奇妙世界里&#xff01;“信号”是一切的基础&#xff0c;理解了信号&#xff0c;就相当于拿到了开启数字信号处理大门的钥匙。 今天&#xff0c;就让我们一起深入探究数字信号处理基础中的“信号”。 一、信号的基本概念 信号&#xff0c;简单来说&#xf…

【持续更新】Mχ Plaayer Pro 1.86.0安卓知名播放器最新免费高级修改版

Mχ Plaayer Pro MOD 版本免费 APK&#xff0c;专为安卓手机和平板打造。这是一款功能强大的视频播放器&#xff0c;具备先进的硬件加速技术和字幕支持功能。 • 硬件加速 - 新增 HW 解码器帮助更多视频格式实现硬件加速。 • 多核心解码 - Mχ Plaayer 是首款支持多核心解码的…

链接 -- 动静态链接 --特点、区别、静态库安装下载

1.链接是什么&#xff1f; 我们的程序&#xff0c;和 库&#xff08;语言一定会有自己的标准库&#xff09; 结合的过程就叫做链接。 2.为什么有链接&#xff1f; 让开发站在巨人的肩膀&#xff0c;提高开发效率。 c语言库&#xff1a; ls /user/include/ 动静态库的特点与区别…

领域驱动设计DDD详解与战术建模落地

一、什么是DDD&#xff1f; 1.1、DDD的概念 Domain-Driven Design&#xff08;领域驱动设计&#xff09;它由Eric Evans在他的2003年出版的书籍《Domain-Driven Design: Tackling Complexity in the Heart of Software》中首次提出。DDD 核心思想是通过领域驱动设计方法定义领…