Образец преобразования объекта

У меня есть несколько разных классов, исходящих из внешних источников (не поддающихся модификации), которые представляют одну и ту же концепцию. Например Address. У меня com.namespace1.Address (с полями houseNum, street, city), com.namespace2.Address (с полями h, s, c), namespace3.com.CoolAddress (с полями house_num, street, city).

Проблема в том, что для некоторых веб-сервисов, которые я использую, требуются определенные типы объектов Address, поэтому мне необходимо создать com.namespace1.Address с учетом namespace3.com.CoolAddress. Поля достаточно просты для сопоставления, но я ищу образец того, как это сделать.

С моей точки зрения, объект-экземпляр AddressConverter не имеет смысла, поскольку не существует состояния (только поведение), и когда классы имеют только поведение, оно сводится к статическим методам в классе утилиты. В долгосрочной перспективе, в любое время, когда мне нужно сопоставлять новые объекты друг с другом, у меня есть одно место для добавления/изменения/удаления методов. Как это могло измениться, но я знаю, где код сидит (в одном месте) и может изменить отображение, когда мне нужно.

Мысли?

Ответы

Ответ 1

Я думаю, что вы ищете класс factory. Шаблон factory используется, когда вам нужно создать экземпляр одного из нескольких связанных классов, который будет определяться factory, а не разработчиком.

См. http://en.wikipedia.org/wiki/Factory_method_pattern

Вы правы, чтобы попытаться сохранить всю эту бизнес-логику в одном месте, вместо того, чтобы делать ClassOne.toClassTwo(), ClassOne.toClassThree(),...

Самый гибкий способ, которым я могу придумать это (но не самый простой), должен состоять в том, чтобы factory начинался с простого класса с использованием только основных распространенных методов и добавлял обработчики к Hashtable или другому контейнер. Таким образом, вам не нужны конкретные реализации всех возможных комбинаций функций.

Конечно, быстрее было бы иметь конкретную реализацию для каждого варианта возможных адресов, но было бы достаточное количество дублированного кода, и было бы немного сложнее добавить новые типы классов адресов.

Ответ 2

Поскольку вы не можете изменять сами классы, я бы предложил реализацию шаблона Adapter для каждого направления. Как вы сказали, сами методы адаптера могут быть статическими, но вы можете группировать оба направления внутри одного класса, чтобы логика находилась в одном месте.

В конце дня вы будете выполнять ту же задачу, независимо от того, что вы называете, или где вы поместите код. Я бы предположил, что оба направления живут в одном файле, так как они часто нуждаются в обновлении, когда меняется любое направление.

Ответ 3

Если вы всегда конвертируете в тот же класс, я бы оставил его простым и поместил весь ваш код преобразования в этот класс, а не беспокоиться о фабриках и т.п., особенно если вы имеете дело только с несколькими разными классами. Почему всегда есть сложный шаблон для этих вещей?!

public class A {

    ...

    public static A convertB(B b) {

    ...

    }
}

Ответ 4

Нужны ли классы для вывода final? Если нет, вы можете подклассифицировать их для создания соответствующих Adapters. В противном случае я бы пошел с предложением dj_segfault для Factory с таблицей обработчиков.

Или, подождите - это просто веб-сервис, с которым вам нужно поговорить? Если это так, не должно быть никаких причин, по которым ваши реализации своих типов данных не могут быть адаптерами, обертывающими входные типы данных или некоторые из ваших промежуточных объектов.