Я пытаюсь разработать картограф, который будет преобразовывать один тип объекта в другой, показанный на диаграмме ниже:
Объект имеет следующую структуру (это не JSON):
{
"type": "DownloadAppComponent",
"name": "Download App",
"contentId": "download-app",
"properties": {
"iosUrl": "http://apple.com",
"androidUrl": "http: //google.com",
"promoText": "Download our app",
"hidden": false
}
Мое первое решение состояло в том, чтобы иметь сопоставитель для каждого типа, но это потребовало много дублирования кода для сопоставления общих атрибутов (например, имя, тип, 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, а затем расширить его с помощью компонента, а затем с помощью конкретных свойств BaseDocument. Однако я не нашел никакого хорошего решения, кроме использования абстрактных классов и наследования в картографах.
Может ли кто-нибудь посоветовать мне, хороший ли это подход или есть ли какие-либо проблемы или другие лучшие решения для моего случая?
Спасибо.
setCommonValues()
. Они не могут быть все в одном классе, потому что он не будет компилироваться. Методmap()
был бы неоднозначным. 28.09.2016super.setCommonValues()
, но я должен добавить еще один уровень наследования для классов преобразователя (т.е.DownloadAppComponentMapper extends ComponentMapper
иComponentMapper extends BaseDocumentMapper
и т. д.). Могу ли я как-то этого избежать? 28.09.2016map
можно переименовать, если их необходимо добавить в тот же класс. Но вы также можете создать для них два класса, не переименовывая его. Если вы выберете один класс с двумя переименованными методамиmap
, вы можете добавить к этому классу методsetCommonValues
. В противном случае лучшим решением будет создать абстрактный класс с конкретным методомsetCommonValue
и абстрактным методомmap
и создать два подкласса для каждой пользовательской реализацииmap
. 28.09.2016