读取和重组不同格式数据集的最佳设计模式?

Optimal design patterns for reading and restructurize datasets with different formats?

问题:

  1. (我想解决这个问题)用 Homogenize image datasets 不同的格式:HDF5、文件夹图像 (不同结构)等

  2. (只是为了给你上下文)然后,数据集被连接起来,由客户端代码预处理并存储在具有 defined/fixed 结构的 HDF5 文件中。

我对 1 的解决方案:

使用如下伪 UML 所示的模板模式:

pseudo-UML diagram

注意到此解决方案 1 的缺点:

  1. 每次新数据集开始运行时都需要更改客户端代码,因为它不知道应该为给定数据集使用哪个 ConcreteStructurizer,我的意思是,客户端会做类似的事情:
if datset_0 use ConcreteStructurizerFolder
ConcreteStructurizerFolder(cfg_dataset_0).reorganize()
.
.
.
if dataset_n use ConcreteStructurizerHDF5
ConcreteStructurizerHDF5(cfg_dataset_n).reorganize()

你能提出一个 better/optimal approach/design 模式吗?

PD:我正在学习软件设计(物理背景),如果你能提供一个pedagogical/well解释的答案,我将不胜感激。

您可以在设计中采用 chain-of-responsibility 模式。

您对 Structurizer 有不同的概括,这是一个好的开始。您的设计定义了 Structurizer 可以在特定类型的数据集上执行的操作。通过添加逻辑来定义它可以处理的数据集类型,让它变得更强大。然后把所有的Structurizer连成一条链。

我们将数据集传递给链,如果第一个 Structurizer 可以处理它,它就会处理它。如果不能,它将数据集传递给下一块进行处理。依此类推。

我的示例引入了一个新接口 DatasetHandler,它将行为添加到

  1. 设置它的下一块。 setNextHandler(DatasetHander)
  2. 定义它可以处理的数据集类型。 handle(Dataset)。布尔值 return 表示数据集是否已成功处理。

我不擅长PHP,但我认为设计模式适用于任何OO语言。下面的例子是 Java.

接口


public interface Structurizer {

    public void reorganize();

    public void createDest();

    public void makeMetaDataJson();

    public void moveToFiles();

}


public interface DatasetHandler {

    public void setNextHandler(DatasetHandler handler);

    public boolean handle(Object dataset);

}

结构化程序实现


public abstract class AbstractStructurizer implements DatasetHandler, Structurizer {

    private String datsetPath;
    private String destPath;
    private boolean overwrite;
    private String metadataFn;
    private boolean possiblyOtherAttributes;
    private DatasetHandler nextHandler;

    @Override
    public void setNextHandler(DatasetHandler handler) {
        if (getNextHandler() == null) {
            this.nextHandler = handler;
        } else {
            this.nextHandler.setNextHandler(handler);
        }
    }

    public boolean tryNextHandler(Object dataset) {
        if (getNextHandler() == null) {
            return false;
        } else {
            return getNextHandler().handle(dataset);
        }
    }

    public String getDatsetPath() {
        return datsetPath;
    }

    public void setDatsetPath(String datsetPath) {
        this.datsetPath = datsetPath;
    }

    public String getDestPath() {
        return destPath;
    }

    public void setDestPath(String destPath) {
        this.destPath = destPath;
    }

    public boolean isOverwrite() {
        return overwrite;
    }

    public void setOverwrite(boolean overwrite) {
        this.overwrite = overwrite;
    }

    public String getMetadataFn() {
        return metadataFn;
    }

    public void setMetadataFn(String metadataFn) {
        this.metadataFn = metadataFn;
    }

    public boolean isPossiblyOtherAttributes() {
        return possiblyOtherAttributes;
    }

    public void setPossiblyOtherAttributes(boolean possiblyOtherAttributes) {
        this.possiblyOtherAttributes = possiblyOtherAttributes;
    }

    public DatasetHandler getNextHandler() {
        return nextHandler;
    }

}

import java.io.File;

public class ConcreteStructurizerFolder extends AbstractStructurizer {

    @Override
    public void reorganize() {
        System.out.println("reorganizing folder dataset...");
    }

    @Override
    public void createDest() {
        System.out.println("creating folder destination...");
    }

    @Override
    public void makeMetaDataJson() {
        System.out.println("making folder metadata json...");
    }

    @Override
    public void moveToFiles() {
        System.out.println("moving folders...");
    }

    @Override
    public boolean handle(Object dataset) {
        if (dataset instanceof File) {
            File fileData = (File) dataset;
            if (fileData.isDirectory()) {
                reorganize();
                createDest();
                makeMetaDataJson();
                moveToFiles();
                return true;
            } else {
                return tryNextHandler(dataset);
            }
        } else {
            return tryNextHandler(dataset);
        }

    }

}

import java.io.File;

public class ConcreteStructurizerHDF5 extends AbstractStructurizer {

    @Override
    public boolean handle(Object dataset) {
        if (dataset instanceof File) {
            File datafile = (File) dataset;
            if (datafile.getName().toLowerCase().endsWith("hdf5")) {
                reorganize();
                createDest();
                makeMetaDataJson();
                moveToFiles();
                return true;
            } else {
                return tryNextHandler(dataset);
            }
        } else {
            return tryNextHandler(dataset);
        }
    }

    @Override
    public void reorganize() {
        System.out.println("reorganizing HDF5 dataset...");
    }

    @Override
    public void createDest() {
        System.out.println("creating HDF5 destination...");
    }

    @Override
    public void makeMetaDataJson() {
        System.out.println("making HDF5 metadata json...");
    }

    @Override
    public void moveToFiles() {
        System.out.println("moving HDF5 files...");
    }

}



public class ConcreteStructurizerUnknown extends AbstractStructurizer {

    @Override
    public boolean handle(Object dataset) {
        System.out.println(String.format("unknown dataset :%s", dataset.getClass()));
        return false;
    }

    @Override
    public void reorganize() {
    }

    @Override
    public void createDest() {
    }

    @Override
    public void makeMetaDataJson() {
    }

    @Override
    public void moveToFiles() {
    }

}

客户端

import java.io.File;

public class Client {

    public static void main(String[] args) {

        // prepare handler chain
        DatasetHandler handlerChain = new ConcreteStructurizerFolder();
        handlerChain.setNextHandler(new ConcreteStructurizerHDF5());
        handlerChain.setNextHandler(new ConcreteStructurizerUnknown());

        // let handler chain handle different type of dataset
        System.out.println("==== test HDF5 dataset ====");
        handlerChain.handle(new File("dataset.HDF5"));
        System.out.println("==== test txt dataset ====");
        handlerChain.handle(new File("Untitled.txt"));
        System.out.println("==== test folder dataset ====");
        handlerChain.handle(new File("C:\"));
        System.out.println("==== test unknown type dataset ====");
        handlerChain.handle("this is an unknown type");
    }

}

输出

==== test HDF5 dataset ====
reorganizing HDF5 dataset...
creating HDF5 destination...
making HDF5 metadata json...
moving HDF5 files...
==== test txt dataset ====
unknown dataset :class java.io.File
==== test folder dataset ====
reorganizing folder dataset...
creating folder destination...
making folder metadata json...
moving folders...
==== test unknown type dataset ====
unknown dataset :class java.lang.String

基本上我们在这里做的是,我们分解 n-th if 案例。对于每个 if 条件,我们将其封装在 DatasetHandler 中。如果将来添加新的数据集类型,则为该类型实现一个新的 Structurizer 并将其添加到链中。如果没有长 运行 if.

,客户端将更易于管理