设计模式 - 抽象文档

目录

定义:

场景:

设计:

目录结构:

结果:

实现:


定义:

抽象文档模式支持处理附加的非静态属性。该模式使用特征的概念来实现类型安全,并将不同类的属性分离到一组接口中。

请考虑一辆由多个部件组成的车。然而,我们不知道具体的汽车是否真的拥有所有的零件,或者只是其中的一部分。我们的汽车是动态的,非常灵活。

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

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

场景:

生活中经常有部分和整体互相嵌套构成完整对象的场景。比如文件夹和文件,文件夹里可以嵌套文件和文件夹。汽车由轮子,发动机,外壳组成。外壳又是玻璃窗和金属框组成。通常我们的做法是定义一个包含自己的对象。抽象出来就是抽象文档设计模式。

设计:

目录结构:

结果:

Here is our car:
-> model: {特斯拉S}
-> price: {10000}
-> parts: {
wheel///米其林轮胎///100}
door///飞虎门窗///300}

实现:

package com.study_abs_doucument.damain;

import com.study_abs_doucument.AbstractDocument;

import java.util.Map;

/**
 * 汽车实体。
 */
public class Car extends AbstractDocument implements HasModel, HasParts, HasPrice {
    public Car(Map<String, Object> properties) {
        super(properties);
    }
}


package com.study_abs_doucument.damain;

import com.study_abs_doucument.Document;

import java.util.Optional;

/**
 * HasModel特性用于静态访问“model”属性。
 */
public interface HasModel extends Document {
    default Optional<String> getModel() {
        return Optional.ofNullable((String) get(Property.MODEL.toString()));
    }
}


package com.study_abs_doucument.damain;

import com.study_abs_doucument.Document;

import java.util.stream.Stream;

/**
 HasParts特性用于静态访问“parts”属性。
 */
public interface HasParts extends Document {


    default Stream<Part> getParts(){
        return children(Property.PARTS.toString(),Part::new);
    }
}




/*
 * The MIT License
 * Copyright © 2014-2021 Ilkka Seppälä
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.study_abs_doucument.damain;

import com.study_abs_doucument.Document;

import java.util.Optional;

/**
 * HasPrice trait for static access to 'price' property.
 */
public interface HasPrice extends Document {

  default Optional<Number> getPrice() {
    return Optional.ofNullable((Number) get(Property.PRICE.toString()));
  }

}


/*
 * The MIT License
 * Copyright © 2014-2021 Ilkka Seppälä
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.study_abs_doucument.damain;

import com.study_abs_doucument.Document;

import java.util.Optional;

/**
 * HasType trait for static access to 'type' property.
 */
public interface HasType extends Document {

  default Optional<String> getType() {
    return Optional.ofNullable((String) get(Property.TYPE.toString()));
  }

}



package com.study_abs_doucument.damain;

import com.study_abs_doucument.AbstractDocument;

import java.util.Map;

/**
 * 部分实体
 */
public class Part extends AbstractDocument implements HasModel, HasPrice, HasType {

    public Part(Map<String, Object> properties) {
        super(properties);
    }
}



package com.study_abs_doucument.damain;

/**
 * 枚举以描述属性类型do
 */
public enum Property {
    PARTS, TYPE, PRICE, MODEL
}



package com.study_abs_doucument;


import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 *
 * @Description 文档接口的抽象实现
 * @Date 2022/1/6 16:42
 */
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 object) {
        properties.put(key,object);
        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);
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(getClass().getName()).append("[");
        properties.forEach((key, value) -> builder.append("[").append(key).append(" : ").append(value)
                .append("]"));
        builder.append("]");
        return builder.toString();
    }
}


package com.study_abs_doucument;

import com.study_abs_doucument.damain.Car;
import com.study_abs_doucument.damain.Property;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 抽象文档模式支持处理附加的非静态属性。该模式使用特征的概念来实现类型安全,
 * 并将不同类的属性分离到一组接口中<p> 在抽象文档模式中,
 * ({@link AbstractDocument})完全实现了{@link Document})接口。
 * 然后定义特征,以便以通常的静态方式访问属性。
 */
public class App {

    public static void main(String[] args) {
        Map<String, ? extends Serializable> wheel = Map.of(Property.TYPE.toString(), "wheel",
                Property.MODEL.toString(), "米其林轮胎",
                Property.PRICE.toString(), 100L);


        Map<String, ? extends Serializable> door = Map.of(Property.TYPE.toString(), "door",
                Property.MODEL.toString(), "飞虎门窗",
                Property.PRICE.toString(), 300L);


        Map<String, Object> car = Map.of(
                Property.MODEL.toString(), "特斯拉S",
                Property.PRICE.toString(), 10000L,
                Property.PARTS.toString(), List.of(wheel, door));


        Car carEntity = new Car(car);

        System.out.println("Here is our car:");
        System.out.println("-> model: {"+ carEntity.getModel().orElseThrow() +"}");
        System.out.println("-> price: {"+ carEntity.getPrice().orElseThrow() + "}");
        System.out.println("-> parts: " + "{");


        carEntity.getParts().forEach(p -> System.out.println(
                p.getType().orElse(null)+"///"+
                p.getModel().orElse(null)+"///"+
                p.getPrice().orElse(null) +"}")
        );



    }
}



package com.study_abs_doucument;

import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * 文档接口
 *
 * 适合有相同属性,但是存在组合,上下级的模式,内嵌模式
 * 文件夹与文件,汽车,树型
 *
 */
public interface Document {

    Void put(String key,Object object);

    Object get(String key);

    //获取子文档的流。
    //子类的构造函数
    <T> Stream<T> children(String key, Function<Map<String,Object>,T> constructor);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值