Фабричный метод для универсального интерфейса - PullRequest
1 голос
/ 31 марта 2011

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

Я пишу фабричный метод для следующего интерфейса.

public interface ITransformer<I, O>
{
   O Transform(I input);
}

Вот возможная реализация интерфейса

public class CarToTruckTransformer : ITransformer<Car, Truck>
{
    public Truck Transform(Car input)
    {
        Truck output = new Truck();
        output.Seats = input.Seats - 2;
        output.BedSize = input.TrunkSize;
        output.Gunrack = true;
        return output;
    }
}

Первая фабрика, которую я сделал, выглядит так

static class TransformerFactory
{
    public static ITransformer<I, O> GetTransformer<I, O>()
    {
        if (typeof(I) == typeof(Car) && typeof(O) == typeof(Truck))
        {
            return (ITransformer<I, O>)new CarToTruckTransformer();
        }
        else
        {
            return null;
       }
    }
}

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

ITransformer<Car, Truck> transf = TransformerFactory.GetTransformer<Car, Truck>();

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

public class TransformerFactory2
{
    public static dynamic GetTransformer(VehicleBase input, VehicleBase output)
    {
        if (input.GetType() == typeof(Car) && output.GetType() == typeof(Truck))
        {
            return (ITransformer<Car, Truck>)new CarToTruckTransformer();
        }
        else
        {
            return null;
        }
    }
}

Но это позволяет мне получить заводской синтаксис, который я хочу.

dynamic transf = TransformerFactory2.GetTransformer(car, truck);

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

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

Спасибо за чтение.

1 Ответ

0 голосов
/ 31 марта 2011

Это далеко не по теме, если вы заинтересованы в изучении ООП и шаблонов, но этот конкретный пример, который вы описываете, может быть довольно аккуратно описан с использованием Func<I,O> делегатов.

например,

var car = getSomeCar();
car.select(c => new Truck{
   :
   :
});

И вы определяете select как универсальный метод расширения для I

например

public static O select<I,O>(this I input, Func<I,O> project)
{
   return project(input);
}

Просто мысль.

Редактировать

Только что проверил это, и оно должно работать нормально :) Переименовано transform в select, чтобы подчеркнуть сходство с оператором Linq.

...