读取和重组不同格式数据集的最佳设计模式?
Optimal design patterns for reading and restructurize datasets with different formats?
问题:
(我想解决这个问题)用 Homogenize image datasets
不同的格式:HDF5、文件夹图像
(不同结构)等
(只是为了给你上下文)然后,数据集被连接起来,由客户端代码预处理并存储在具有 defined/fixed 结构的 HDF5 文件中。
我对 1 的解决方案:
使用如下伪 UML 所示的模板模式:
pseudo-UML diagram
注意到此解决方案 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
,它将行为添加到
- 设置它的下一块。
setNextHandler(DatasetHander)
- 定义它可以处理的数据集类型。
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.
,客户端将更易于管理
问题:
(我想解决这个问题)用 Homogenize image datasets 不同的格式:HDF5、文件夹图像 (不同结构)等
(只是为了给你上下文)然后,数据集被连接起来,由客户端代码预处理并存储在具有 defined/fixed 结构的 HDF5 文件中。
我对 1 的解决方案:
使用如下伪 UML 所示的模板模式:
pseudo-UML diagram
注意到此解决方案 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
,它将行为添加到
- 设置它的下一块。
setNextHandler(DatasetHander)
- 定义它可以处理的数据集类型。
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.