gpt4 book ai didi

java - 使用自定义转换器映射对象类型

转载 作者:行者123 更新时间:2023-12-02 03:20:11 27 4
gpt4 key购买 nike

我正在尝试设计一个映射器,它将一种对象类型转换为另一种对象类型,如下图所示:

enter image description here

该对象的结构如下(不是 JSON):

{
"type": "DownloadAppComponent",
"name": "Download App",
"contentId": "download-app",
"properties": {
"iosUrl": "http://apple.com",
"androidUrl": "http: //google.com",
"promoText": "Download our app",
"hidden": false
}

我的第一个解决方案是为每种类型提供映射器,但这需要大量重复代码来映射公共(public)属性(即名称、类型、contentId)。

public DownloadAppComponent map(CmsDocument cmsDocument) {
DownloadAppComponent downloadAppComponent = new DownloadAppComponent();

downloadAppComponent.setType(cmsDocument.getType()); // <-- this will be duplicated in each mapper
downloadAppComponent.setName(cmsDocument.getName()); // <-- this will be duplicated in each mapper
downloadAppComponent.setContentId(cmsDocument.getText(CONTENT_ID_PATH)); // <-- this will be duplicated in each mapper
downloadAppComponent.setIosURL(cmsDocument.getText(IOS_URL_PATH));
downloadAppComponent.setAndroidURL(cmsDocument.getText(ANDROID_URL_PATH));
downloadAppComponent.setHidden(Boolean.parseBoolean(cmsDocument.getText(HIDE_PATH)));
downloadAppComponent.setPromoText(cmsDocument.getText(DOWNLOAD_PROMO_TEXT_PATH));

return downloadAppComponent;
}

我一直在尝试重构该代码,并提出了通用的 BaseDocumentMapper:

public BaseDocument map(CmsDocument cmsDocument) {
BaseDocument document = documentsMapperFactory.getMapper(cmsDocument.getType()).map(cmsDocument);
document.setType(cmsDocument.getType());
document.setName(cmsDocument.getName());
document.setContentId(cmsDocument.getText(CONTENT_ID_PATH));
return document;
}

documentsMapperFactory返回特定的映射器,该映射器仅映射类型相关的属性并返回该对象实例。

但是继承还有更多级别,我只有一种类型值,可以将其解析为具体映射器。因此,我必须在每个组件映射器中重复组件的特定字段映射。我在想,既然我知道层次结构,我可以创建一些映射器,将文档从上到下映射,即创建第一个 DownloadAppComponent,然后使用 Component 扩展它,然后使用 BaseDocument 特定属性扩展它。然而,除了在映射器中使用抽象类和继承之外,我还没有找到任何好的解决方案。

如果这是一个好的方法,或者对于我的案例有任何问题或其他更好的解决方案,有人可以建议我吗?

谢谢。

最佳答案

至少有三种选择。第一个是更通用的,将 CmsDocument 的概念与 BaseDocument 完全分开。

另外两个选项链接 BaseDocumentCmsDocument 类,因此它是选项选择的设计选择。

第一个选项您可以根据两个对象均派生自 BaseDocument 的事实,创建一个方法来设置公共(public)值。

....

private void setCommonValues(BaseDocument doc, CmsDocument cmsDocument) {
doc.setType(cmsDocument.getType());
doc.setName(cmsDocument.getName());
doc.setContentId(cmsDocument.getText(CONTENT_ID_PATH));
}



public DownloadAppComponent map(CmsDocument cmsDocument) {
DownloadAppComponent downloadAppComponent = new DownloadAppComponent();

// Call setCommonValues
setCommonValues(downloadAppComponent, cmsDocument);

downloadAppComponent.setIosURL(cmsDocument.getText(IOS_URL_PATH));
downloadAppComponent.setAndroidURL(cmsDocument.getText(ANDROID_URL_PATH));
downloadAppComponent.setHidden(Boolean.parseBoolean(cmsDocument.getText(HIDE_PATH)));
downloadAppComponent.setPromoText(cmsDocument.getText(DOWNLOAD_PROMO_TEXT_PATH));

return downloadAppComponent;
}

其他函数也类似

public BaseDocument map(CmsDocument cmsDocument) {
BaseDocument document = documentsMapperFactory.getMapper(cmsDocument.getType()).map(cmsDocument);

// Call setCommonValues to remove duplication of code
setCommonValues(document, cmsDocument);
return document;
}
<小时/>

第二个选项

BaseDocument类中创建一个方法init

private void init(CmsDocument cmsDocument) {
this.setType(cmsDocument.getType());
this.setName(cmsDocument.getName());
this.setContentId(cmsDocument.getText(CONTENT_ID_PATH));
}

在 map 正文中

public DownloadAppComponent map(CmsDocument cmsDocument) {
DownloadAppComponent downloadAppComponent = new DownloadAppComponent();

// Call init
downloadAppComponent.init(cmsDocument);

downloadAppComponent.setIosURL(cmsDocument.getText(IOS_URL_PATH));
downloadAppComponent.setAndroidURL(cmsDocument.getText(ANDROID_URL_PATH));
downloadAppComponent.setHidden(Boolean.parseBoolean(cmsDocument.getText(HIDE_PATH)));
downloadAppComponent.setPromoText(cmsDocument.getText(DOWNLOAD_PROMO_TEXT_PATH));

return downloadAppComponent;
}

其他函数也类似

public BaseDocument map(CmsDocument cmsDocument) {
BaseDocument document = documentsMapperFactory.getMapper(cmsDocument.getType()).map(cmsDocument);

// Call init
document.init(cmsDocument);

return document;
}
<小时/>

第三个选项

BaseDocument 上创建一个构造函数,将 CmsDocument 作为参数

public BaseDocument(CmsDocument cmsDocument) {
this.setType(cmsDocument.getType());
this.setName(cmsDocument.getName());
this.setContentId(cmsDocument.getText(CONTENT_ID_PATH));
}

在 DownloadAppComponent 中

 public DownloadAppComponent(CmsDocument cmsDocument) {
super(cmsDocument);
this.setIosURL(cmsDocument.getText(IOS_URL_PATH));
this.setAndroidURL(cmsDocument.getText(ANDROID_URL_PATH));
this.setHidden(Boolean.parseBoolean(cmsDocument.getText(HIDE_PATH)));
this.setPromoText(cmsDocument.getText(DOWNLOAD_PROMO_TEXT_PATH));

}

在这种情况下,您不需要map方法,您可以直接构建带参数调用构造函数的对象。

<小时/>

如果您需要一个带有 map 方法的类,该方法可以返回两个不同的实例,您可以将所需的类型作为参数传递:

public class Mapper {
private void setCommonValues(BaseDocument doc, CmsDocument cmsDocument) {
doc.setType(cmsDocument.getType());
doc.setName(cmsDocument.getName());
doc.setContentId(cmsDocument.getText(CONTENT_ID_PATH));
}

public BaseDocument map(CmsDocument cmsDocument, Class<? extends BaseDocument> clazz) {
BaseDocument doc = null;
if (clazz.getCanonicalName().equals(DownloadAppComponent.class.getCanonicalName()) {
DownloadAppComponent appComponent = new DownloadAppComponent();
doc = appComponent;
appComponent.setIosURL(cmsDocument.getText(IOS_URL_PATH));
appComponent.setAndroidURL(cmsDocument.getText(ANDROID_URL_PATH));
appComponent.setHidden(Boolean.parseBoolean(cmsDocument.getText(HIDE_PATH)));
appComponent.setPromoText(cmsDocument.getText(DOWNLOAD_PROMO_TEXT_PATH));

} else {
doc = new BaseDocument();
}
setCommonValues(doc);
return doc;
}
}

您可以将其调用为:

Mapper mapper = new Mapper();
CmsDocument cmsDocument = ...

BaseDocument doc = mapper.map(cmsDocument, BaseDocument.class);

DownloadAppComponent downloadAppComponent = (DownloadAppComponent) mapper.map(cmsDocument, DownloadAppComponent.class);

关于java - 使用自定义转换器映射对象类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39728245/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com