Что мне делать, если у меня есть метод фабрики, который требует разных параметров для разных реализаций? - PullRequest
2 голосов
/ 02 апреля 2010

У меня есть интерфейс, IMessage и класс, в котором есть несколько методов для создания различных типов сообщений, например:

class MessageService
{
    IMessage TypeAMessage(param 1, param 2)
    IMessage TypeBMessage(param 1, param 2, param 3, param 4)
    IMessage TypeCMessage(param 1, param 2, param 3)
    IMessage TypeDMessage(param 1)    
}

Я не хочу, чтобы этот класс делал всю работу по созданию этих сообщений, поэтому он просто делегирует MessageCreatorFactory, который выдает IMessageCreator в зависимости от заданного типа (перечисление, основанное на типе сообщения TypeA , TypeB, TypeC и т. Д.)

interface IMessageCreator
{
     IMessage Create(MessageParams params);
}

Итак, у меня есть 4 реализации IMessageCreator: TypeAMessageCreator, TypeBMessageCreator, TypeCMessageCreator, TypeDMessageCreator

Я согласен с этим, за исключением того факта, что, поскольку каждый тип требует различных параметров, мне пришлось создать объект MessageParams, который содержит 4 свойства для 4 различных параметров, но только некоторые из них используются в каждом IMessageCreator ,

Есть ли альтернатива этому? Еще одна мысль, которая у меня была, заключалась в том, чтобы иметь массив параметров в качестве параметра в методе Create, но это кажется еще хуже, поскольку вы не представляете, что это за параметры. Или создать несколько перегрузок Create в интерфейсе, и некоторые из них выдают исключение, если они не подходят для данной конкретной реализации (т. Е. Вы вызвали метод, которому нужно больше параметров, поэтому вы должны были вызвать одну из других перегрузок.)

Кажется ли это нормально? Есть ли лучшее решение?

Ответы [ 3 ]

5 голосов
/ 02 апреля 2010

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

Например, если вы указываете enum (TypeA, TypeB, TypeC), вы можете просто создать TypeA напрямую. Если вы хотите разрешить использование нескольких подклассов для реализации TypeA, создайте фабрику только для TypeA ...

0 голосов
/ 02 апреля 2010

Я не вижу причин, по которым ваши TypeXMessageCreator классы должны реализовывать общий интерфейс. Я бы полностью избавился от IMessageCreator и просто имел бы 4 отдельные фабрики для создания IMessage объектов.

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

Помните, что наследование не для повторного использования кода.

0 голосов
/ 02 апреля 2010

По моему мнению, иметь четыре перегрузки IMessage Create гораздо лучше, чем иметь один метод с MessageParam.

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

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

...