【设计模式】JAVA Design Patterns——Abstract-document(抽象文档模式)

简介: 【设计模式】JAVA Design Patterns——Abstract-document(抽象文档模式)

🔍 目的


使用动态属性,并在保持类型安全的同时实现非类型化语言的灵活性。


🔍 解释


抽象文档模式使您能够处理其他非静态属性。 此模式使用特征的概念来实现类型安全,并将不同类的属性分离为一组接口

真实世界例子

考虑由多个部分组成的计算机。 但是,我们不知道特定计算机是否真的拥有所有零件,或者仅仅是零件中的一部分。 我们的计算机是动态而且非常灵活的。

通俗的说

抽象文档模式允许在对象不知道的情况下将属性附加到对象。

维基百科

面向对象的结构设计模式,用于组织松散类型的键值存储中的对象并使用类型化的视图公开数据。 该模式的目的是在强类型语言中实现组件之间的高度灵活性,在这种语言中,可以在不丢失类型安全支持的情况下,将新属性动态地添加到对象树中。 该模式利用特征将类的不同属性分成不同的接口。


🔍 程序示例

让我们首先定义基类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);
  }
  ...
}


接下来,我们定义一个枚举“属性”和一组类型,价格,模型和零件的接口。 这使我们能够为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构造和使用方式。

    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))
    );
 
    // Constructing parts and car
    // Here is our car:
    // model: 300SL
    // price: 10000
    // parts: 
    // wheel/15C/100
    // door/Lambo/300


🔍 类图

8e945deb4c9f4fadaa256e15629347ba.png


🔍 适用性


使用抽象文档模式当

  • 需要即时添加新属性
  • 你想要一种灵活的方式来以树状结构组织域
  • 你想要更宽松的耦合系统

5ff60e89324042e3a1f29fbe59cffc14.gif

相关文章
|
15天前
|
JavaScript Java 测试技术
Java项目基于ssm+vue.js的网上手机销售系统附带文章和源代码设计说明文档ppt
Java项目基于ssm+vue.js的网上手机销售系统附带文章和源代码设计说明文档ppt
23 0
|
3天前
|
数据可视化 Java API
【JAVA】javadoc,如何生成标准的JAVA API文档
【JAVA】javadoc,如何生成标准的JAVA API文档
6 0
|
7天前
|
设计模式 新零售 Java
设计模式最佳套路5 —— 愉快地使用工厂方法模式
工厂模式一般配合策略模式一起使用,当系统中有多种产品(策略),且每种产品有多个实例时,此时适合使用工厂模式:每种产品对应的工厂提供该产品不同实例的创建功能,从而避免调用方和产品创建逻辑的耦合,完美符合迪米特法则(最少知道原则)。
29 6
|
7天前
|
设计模式 Java 关系型数据库
设计模式第2弹:工厂方法模式
type ComputerProduct struct{} // 实现工厂方法 func (computer ComputerProduct) GetInformation() string { return "电脑,官方称呼计算机,主要用于进行数据运算的一台机器。" }
22 4
|
7天前
|
设计模式 XML Java
【设计模式】第三篇:一篇搞定工厂模式【简单工厂、工厂方法模式、抽象工厂模式】
三 结尾 如果文章中有什么不足,欢迎大家留言交流,感谢朋友们的支持! 如果能帮到你的话,那就来关注我吧!如果您更喜欢微信文章的阅读方式,可以关注我的公众号
17 5
|
8天前
|
设计模式 架构师 NoSQL
设计模式-工厂方法模式和抽象工厂模式
 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
186 0
|
9天前
|
Java 数据安全/隐私保护
Java使用PDFBox开发包实现对PDF文档内容编辑与保存
Java使用PDFBox开发包实现对PDF文档内容编辑与保存
21 7
|
15天前
|
JavaScript Java 测试技术
Java项目基于ssm+vue.js的生鲜在线销售系统附带文章和源代码设计说明文档ppt
Java项目基于ssm+vue.js的生鲜在线销售系统附带文章和源代码设计说明文档ppt
13 0
|
15天前
|
JavaScript Java 测试技术
Java项目基于ssm+vue.js的经典电影推荐网站附带文章和源代码设计说明文档ppt
Java项目基于ssm+vue.js的经典电影推荐网站附带文章和源代码设计说明文档ppt
12 0
|
15天前
|
JavaScript Java 测试技术
Java项目基于ssm+vue.js的餐馆点餐系统附带文章和源代码设计说明文档ppt
Java项目基于ssm+vue.js的餐馆点餐系统附带文章和源代码设计说明文档ppt
17 0