У меня следующий сценарий (упрощенный) в Spring REST API.
public class FooService
{
public void createFoo(FooData data) { ... }
}
public class FooController
{
public void makeFooAnymous(AnymousFooForm aif) { ... }
public void makeFooUser(UserFooForm uif) { ... }
}
Обе конечные точки makeIssueAnymous и makeIssueUser хотят вызвать createIssue, потому что они делают то же самое, но имеют некоторые различия в API.
Раствор I
В контроллере обе конечные точки вызывают метод
private <T> void createFooUsing(T fooForm, Function<T, FooData> formToDataConverter)
{
// doSomeCommonConversionLogic
try
{
createSomeResource();
fooService.saveFoo(formToDataConverter.apply(fooForm), andMaybeAnotherParam);
} catch (SomeExcp e) { doSomeThingSpecial() }
}
И классы форм выглядят так:
class UserFooForm
{
public String someData;
public FooData toFooData(String otherField) { ... }
}
class AnymousFooForm
{
public String someDatas;
public String otherField;
public FooData toFooData(int paramFromPath) { ... }
}
А код в методе cotroller выглядит так:
public void makeFooUser(@RequestBody UserFooForm fooForm)
{
return createFooUsing(fooForm, f -> f.toFooData("abc"));
}
public void makeFooAnymous(@RequestBody UserFooForm fooForm)
{
return createFooUsing(fooForm, f -> f.toFooData(123));
}
Решение II:
Превратить FooData в интерфейс
interface FooData {
String getSomeData();
String getOtherField();
}
И заставьте UserIssueForm и AnymousIssueForm реализовать интерфейс, скопируйте «doSomeCommonConversionLogic» и просто передайте его методу сервиса createIssue.
public void makeFooUser(@RequestBody UserFooForm fooForm)
{
// doSomeCommonConversionLogic
try
{
createSomeResource();
fooForm.prepare("abc");
fooService.saveFoo(fooForm, andMaybeAnotherParam);
} catch (SomeExcp e) { doSomeThingSpecial() }
}
public void makeFooAnymous(@RequestBody AnymousFooForm fooForm)
{
// doSomeCommonConversionLogic
try
{
createSomeResource();
fooForm.prepare(123);
fooService.saveFoo(fooForm, andMaybeAnotherParam);
} catch (SomeExc e) { doSomeThingSpecial() }
}
Было бы замечательно, если бы не было такого общего кода. Это связано с HTTP, и я не хочу иметь его в службе.
Что лучше? А может что-то еще?