Я прочитал и получил удовольствие от статьи http://blog.jooq.org/2012/01/05/the-java-fluent-api-designer-crash-course/ от Lukas Eder, и я хотел бы создать Fluent Interface для класса.Свободный интерфейс (Java) для объекта с геттерами и сеттерами
Класс имеет четыре функции («слова» fill1 to fill4), которые позволяют устанавливать атрибуты объектов и четыре функции («слова» get1 to get4), которые получают эти атрибуты, но только если установлены необходимые атрибуты:
Сначала я должен заполнить основные настройки (fill1). После этого я либо могу получить некоторые из этих настроек (get1 to get3), которые являются строками. Или я могу заполнить дополнительную информацию (fill2 to fill4). Но только после каждый fill2 to fill4 был вызван хотя бы один раз, может быть вызван окончательный get4. Как мне это сделать?
Первый граф (состояния - черные точки) показывает, что я хочу делать, но как вы можете видеть? отмечает часть, которая не ясна, потому что, если она оставлена, как она есть в первом графе, она позволит вызывать get4, даже если был вызван только один из fill2 to fill4.
Второй график заставит каждого fill2 заполнить4 вызывается, но информирует порядок и ограничивает это, если я хочу изменить, например. fill3, мне также нужно сбросить fill2 и fill4.
Последний график будет делать то, что я хочу, но он имеет состояний! Теперь, если я предполагаю, что просто добавлю еще один атрибут в группу fill2, чтобы заполнить4, число состояний взорвется еще больше.
Edit: Кроме того, после того, как думать об этом еще немного, я заметил, что, как я бы это сделать (смотри ниже), даже не будет в состоянии осуществить последний график, потому что после того, как fill2 вызывается, мы можем быть в разных состояниях - в зависимости от того, что произошло раньше.
Что делать/делать?
Редактировать: Я реализую свои беглые интерфейсы немного как фасад (если у меня есть шаблон дизайна справа). Я имею в виду: я оставляю фактический класс почти нетронутым - возвращая его (как в цепочке методов), но имея соответствующие интерфейсы состояния как возвращаемые значения в сигнатурах метода. Состояния представлены вложенными интерфейсами. Пример:
public class MyClass implements MyInterface.Empty, MyInterface.Full {
String stuff;
private MyClass(){};
public static MyInterface.Empty manufactureNewInstance(){
return new MyClass();
}
public MyInterface.Full fillStuff(String stuff){
this.stuff = stuff;
return this;
}
public String getStuff(){
return stuff;
}
}
public interface MyInterface {
public interface Empty {
public MyInterface.Full fillStuff();
}
public interface Full {
public String getStuff();
}
}
public class MyMain {
pulic static void main(String[] args) {
// For explaination:
MyClass.Empty myclassEmpty = MyClass.manufactureNewInstance();
MyClass.Full myclassFull = myclassEmpty.fillStuff("Hello World 1!");
String result1 = myclassEmpty.getStuff();
// As fluent chaining:
String result2 = MyClass.manufactureNewInstance()
.fillStuff("Hello World 2!")
.getStuff();
}
}
Большое спасибо. Эти два проекта генерации кода кажутся увлекательными. Написание всего этого кода для генерации кода, похоже, не быстрее, чем просто писать интерфейсы/классы напрямую. Я обновил свой вопрос относительно части фасада. – Make42
Генерация кода может помочь вам автоматически разрешить все перестановки вашего свободного интерфейса. Например, я мог бы попросить вас написать программу, которая печатает все перестановки чисел 1-5. Это будет короткая программа, но для записи всех чисел потребуется много времени. Это похоже на ваш свободный интерфейс. Вы можете описать генератор кода, как создать все возможные перестановки без необходимости записывать их самостоятельно. Это часто меньше подвержено ошибкам (особенно при рефакторинге) и быстрее реализуется. –
Хорошая точка. Это может помочь найти ответ на мой вопрос, но пока не отвечает (см. Правки). Тем не менее: Большое спасибо. – Make42