Как построить последовательность в вызовах методов свободного интерфейса

Привет, я хотел бы создать удобный интерфейс для создания объекта типа фабрики или строителя.

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

public class CarBuilder
{

   public  CarBuilder()
   {
       car = new Car();
   }
    private Car car;

    public CarBuilder AddEngine(IEngineBuilder engine)
    {
        car.Engine = engine.Engine();
        return this;
    }

    public CarBuilder AddWheels(IWheelsBuilder wheels)
    {
        car.Wheels = wheels.Wheels();
        return this;
    }
    public CarBuilder AddFrame(IFrameBuilder frame)
    {
        car.Frame = frame.Frame();
        return this;
    }

    public Car BuildCar()
    {
        return car;
    }

}

с этим я мог бы построить такую ​​машину:

 Car c = builder.AddFrame(fBuilder).AddWheels(wBuilder).AddEngine(eBuilder).BuildCar();

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

И как бы это было или что было бы хорошей реализацией, если бы сам EngineBuilder имел плавный API, такой как eBuilder.Cylinders(12).WithPistons()....

Возможно ли иметь что-то подобное

Car c = builder.AddFrame(fBuilder).AddWheels(wBuilder).AddEngine(x=>x.WithCylinders(12).WithPistons()).BuildCar();

Итак, в общем, как структурировать поток свободного интерфейса и как вкладывать плавные интерфейсы?


person silverfighter    schedule 24.02.2011    source источник


Ответы (2)


Вместо одного класса CarBuilder, который предоставляет все методы, у вас есть несколько классов, каждый из которых предоставляет только методы, соответствующие «состоянию» строящегося автомобиля.

Учитывая ваш пример, CarBuilder предложит только AddFrame. Вместо того, чтобы возвращать this, AddFrame возвращает объект класса CarBuilderWithFrame, который предлагает только AddWheels, который возвращает объект класса CarBuilderWithFrameAndWheels, который предлагает только AddEngine, который возвращает объект класса CarBuilderWithEverything, который предлагает только Build.

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

Мне нравится пример для печати. Объект Printer может возвращать объект PrintJob, предлагающий три метода: Cancel, Print или StartPage. Метод StartPage вернет объект Page, который дает вам методы для всех команд рисования, один из которых называется EndPage, который возвращает вам объект PrintJob. Это упрощает жесткое кодирование простого задания на печать.

Printer.StartPrintJob().StartPage().DrawText("Title").DrawIcon("logo.png").EndPage().Print();
person Adrian McCarthy    schedule 15.11.2017

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

person TJHeuvel    schedule 24.02.2011
comment
Я хочу создать свободный API для костюма dsl, такого как свободный nhibernate... Больше похоже на цепочку методов - person silverfighter; 25.02.2011