Jak mam 7 atrybutów klasy POJO, finalne inicjowane w konstruktorze to lepiej robić konsturktor z 7 parametrami obowiązkowymi czy buildera?

- Rejestracja:prawie 7 lat
- Ostatnio:dzień
- Lokalizacja:Kraków
- Postów:2000
Wg mnie wtedy lepiej
- nauczyć się Kotlina
- zdefiniować sobie POJO z domyślnymi parametrami w
data class
ie - zapomnieć o builderach i tworzyć sobie obiekty jak człowiek, z tymi parametrami których akurat potrzebujesz
- side note:
data class
daje Ci gotową metodęcopy()
z możliwością nadpisania wybranych parametrów w kopii obiektu

- Rejestracja:prawie 10 lat
- Ostatnio:ponad 2 lata
- Postów:81
Napisanie buildera, który zapewnia ci parametry obowiązkowe (i to 7) nie jest takie proste :). Jak masz aż 7 parametrów to znak ze cos jest nie tak z twoim POJO, chyba ze to szpring :) Lombok może być pomocny ;)

- Rejestracja:prawie 17 lat
- Ostatnio:24 dni
Najpierw sprawdź, czy nie możesz wyodrębnić innej klasy z tych parametrów. Np. klasa User
dostaje firstName
, secondName
, surname
. Te trzy pola można z powodzeniem przerzucić do klasy UserName
i ją wstrzykiwać przez konstruktor do klasy User
. Jeśli nadal to nie wystarcza to idź w buildera.

- Rejestracja:ponad 6 lat
- Ostatnio:ponad rok
- Lokalizacja:Zielona Góra
- Postów:83
superdurszlak napisał(a):
Wg mnie wtedy lepiej
- nauczyć się Kotlina
- zdefiniować sobie POJO z domyślnymi parametrami w
data class
ie- zapomnieć o builderach i tworzyć sobie obiekty jak człowiek, z tymi parametrami których akurat potrzebujesz
- side note:
data class
daje Ci gotową metodęcopy()
z możliwością nadpisania wybranych parametrów w kopii obiektu
W javie 12 jest coś podobnego - zamiast data class
masz record
. :) Chociaż nie wiem czy będzie odpowiednik copy
EDIT: miało być coś podobnego, jednak to nie prawda; @Wibowit dzięki za sprostowanie






- Rejestracja:około 8 lat
- Ostatnio:ponad 4 lata
- Postów:1703
Pokażę Wam na kodzie o co chodzi.
Było tak:
public interface Result {
boolean isValid();
ResultSalary getSalary();
Optional<Integer> getWorkExpInMonths();
Set<String> getTech();
Optional<String> getArea();
Optional<Integer> getAge();
Optional<ContractType> getContractType();
}
final class ResultImpl implements Result {
private final boolean isValid;
private final MessageSalary salary;
private final Optional<Integer> experience;
private final Set<String> technologies;
private final Optional<String> location;
private final Optional<Integer> age;
private final Optional<ContractType> contractType;
public ResultImpl (String content) {
Scrapper<Integer> scrapperExp = new ScrapperExpFactory().produceDefault();
Scrapper<String> scrapperTech = new ScrapperTechFactory().produceDefault();
Scrapper<String> scrapperLocation = new ScrapperLocationFactory().produceDefault();
Scrapper<Integer> scrapperAge = new ScrapperAgeFactory().produceDefault();
Scrapper<ContractType> scrapperContractType = new ScrapperContractTypeFactory().produceDefault();
this.salary = new MessageSalary4programmers(content);
this.experience = scrapperExp.scrapeFrom(content).stream().min(Comparator.naturalOrder());
this.technologies = new HashSet<String>(scrapperTech.scrapeFrom(content));
this.location = scrapperLocation.scrapeFrom(content).stream().findFirst();
this.age = scrapperAge.scrapeFrom(content).stream().findFirst();
this.contractType = scrapperContractType.scrapeFrom(content).stream().findFirst();
this.isValid = salary.getValueMonth().isPresent() && experience.isPresent() && technologies.size() > 0;
}
@Override
public boolean isValid() {
return this.isValid;
}
@Override
public MessageSalary getSalary() {
return this.salary;
}
@Override
public Optional<Integer> getWorkExpInMonths() {
return this.experience;
}
@Override
public Set<String> getTech() {
return technologies;
}
@Override
public Optional<String> getArea() {
return location;
}
@Override
public Optional<Integer> getAge() {
return age;
}
@Override
public Optional<ContractType> getContractType() {
return contractType;
}
}
interface ResultSalary {
Optional<Integer> getValueMonth();
Optional<NettoBruttoSalary> getNettoBrutto();
Optional<CurrencySalary> getCurrency();
double getExchangeRate();
}
final class ResultSalaryImpl implements ResultSalary {
private final Optional<Integer> value;
private final Optional<NettoBruttoSalary> netGross;
private final Optional<CurrencySalary> currency;
private final double exchangeRate;
public ResultSalaryImpl (String content) {
Scrapper<Integer> scrapperSalaryValue = new ScrapperSalaryValueFactory().produceDefault();
Scrapper<NettoBruttoSalary> scrapperNetGross = new ScrapperNetGrossFactory().produceDefault();
Scrapper<CurrencySalary> scrapperCurrency = new ScrapperCurrencyFactory().produceDefault();
this.value = scrapperSalaryValue.scrapeFrom(content).stream().findFirst();
this.netGross = scrapperNetGross.scrapeFrom(content).stream().findFirst();
this.currency = scrapperCurrency.scrapeFrom(content).stream().findFirst();
this.exchangeRate = currency.isPresent() ?
(GlobalDataHolder.CURRENCIES.getMap().get(currency.get().toString())) : 1.0;
}
@Override
public Optional<Integer> getValueMonth() {
return value;
}
@Override
public Optional<NettoBruttoSalary> getNettoBrutto() {
return netGross;
}
@Override
public Optional<CurrencySalary> getCurrency() {
return currency;
}
@Override
public double getExchangeRate() {
return exchangeRate;
}
}
zamieniłem na:
public final class Result {
public final boolean isValid;
public final MessageSalary salary;
public final Optional<Integer> experience;
public final Set<String> technologies = new HashSet<>();
public final Optional<String> location;
public final Optional<Integer> age;
public final Optional<ContractType> contractType;
public Result(Builder builder) {
this.isValid = builder.isValid;
this.salary = builder.salary;
this.experience = builder.experience;
this.technologies.addAll(builder.technologies);
this.location = builder.location;
this.age = builder.age;
this.contractType = builder.contractType;
}
public static class Builder {
boolean isValid;
MessageSalary salary;
Optional<Integer> experience;
Set<String> technologies;
Optional<String> location;
Optional<Integer> age;
Optional<ContractType> contractType;
public Builder setValid(boolean isValid) {
this.isValid = isValid;
return this;
}
public Builder setMessageSalary(MessageSalary salary) {
this.salary = salary;
return this;
}
public Builder setExperience(Optional<Integer> experience) {
this.experience = experience;
return this;
}
public Builder setTechnologies(Set<String> technologies) {
this.technologies = technologies;
return this;
}
public Builder setLocation(Optional<String> location) {
this.location = location;
return this;
}
public Builder setAge(Optional<Integer> age) {
this.age = age;
return this;
}
public Builder setContractType(Optional<ContractType> contractType) {
this.contractType = contractType;
return this;
}
public Result build() {
return new Result(this);
}
}
}
interface ResultFactory {
Result createResult(String content);
}
final class ResultFactoryImpl implements ResultFactory {
@Override
public ResultFactoryImpl createResult(String content) {
Scrapper<Integer> scrapperExp = new ScrapperExpFactory().produceDefault();
Scrapper<String> scrapperTech = new ScrapperTechFactory().produceDefault();
Scrapper<String> scrapperLocation = new ScrapperLocationFactory().produceDefault();
Scrapper<Integer> scrapperAge = new ScrapperAgeFactory().produceDefault();
Scrapper<ContractType> scrapperContractType = new ScrapperContractTypeFactory().produceDefault();
MessageSalary salary = new MessageSalary4programmersFactory().createMessageSalary(content);
Optional<Integer> experience = scrapperExp.scrapeFrom(content).stream().min(Comparator.naturalOrder());
Set<String> technologies = new HashSet<String>(scrapperTech.scrapeFrom(content));
Optional<String> location = scrapperLocation.scrapeFrom(content).stream().findFirst();
Optional<Integer> age = scrapperAge.scrapeFrom(content).stream().findFirst();
Optional<ContractType> contractType = scrapperContractType.scrapeFrom(content).stream().findFirst();
boolean isValid = salary.value.isPresent() && experience.isPresent() && technologies.size() > 0;
return new Result.Builder()
.setMessageSalary(salary)
.setExperience(experience)
.setTechnologies(technologies)
.setLocation(location)
.setAge(age)
.setContractType(contractType)
.setValid(isValid)
.build();
}
}
final class ResultSalary {
public final Optional<Integer> value;
public final Optional<NetGrossSalary> nettoBrutto;
public final Optional<CurrencySalary> currency;
public final double exchangeRate;
public ResultSalary (Builder builder) {
this.value = builder.value;
this.nettoBrutto = builder.nettoBrutto;
this.currency = builder.currency;
this.exchangeRate = builder.exchangeRate;
}
public static class Builder {
Optional<Integer> value;
Optional<NetGrossSalary> nettoBrutto;
Optional<CurrencySalary> currency;
double exchangeRate;
public Builder setValue(Optional<Integer> value) {
this.value = value;
return this;
}
public Builder setNettoBrutto(Optional<NetGrossSalary> nettoBrutto) {
this.nettoBrutto = nettoBrutto;
return this;
}
public Builder setCurrency(Optional<CurrencySalary> currency) {
this.currency = currency;
return this;
}
public Builder setExchangeRate(double exchangeRate) {
this.exchangeRate = exchangeRate;
return this;
}
public ResultSalary build() {
return new ResultSalary(this);
}
}
}
interface MessageSalaryFactory {
MessageSalary createResultSalary(String content);
}
final class ResultSalaryFactoryImpl implements ResultSalaryFactory {
@Override
public ResultSalaryFactoryImpl createResultSalary(String content) {
Scrapper<Integer> scrapperSalaryValue = new ScrapperSalaryValueFactory().produceDefault();
Scrapper<NetGrossSalary> scrapperNetGross = new ScrapperNetGrossFactory().produceDefault();
Scrapper<CurrencySalary> scrapperCurrency = new ScrapperCurrencyFactory().produceDefault();
Optional<Integer> value = scrapperSalaryValue.scrapeFrom(content).stream().findFirst();
Optional<NetGrossSalary> netGross = scrapperNetGross.scrapeFrom(content).stream().findFirst();
Optional<CurrencySalary> currency = scrapperCurrency.scrapeFrom(content).stream().findFirst();
double exchangeRate = currency.isPresent() ?
(GlobalDataHolder.CURRENCIES.getMap().get(currency.get().toString())) : 1.0;
return new ResultSalaryFactory.Builder()
.setValue(value)
.setNettoBrutto(netGross)
.setCurrency(currency)
.setExchangeRate(exchangeRate)
.build();
}
}
Chyba źle zrobiłęm, bo 120 linijek zaminiłem na 180
- Rejestracja:około 7 lat
- Ostatnio:13 minut
- Postów:908
W przykładzie z interfejsem możesz użyć biblioteki Immutables, która generuje automatycznie implementację i builder. Ewentualnie możesz użyć lomboka. Najlepiej jednak jest wybrać np. Kotlina zamiast pluginów do kompilatora. Kotlin w sumie też jest pluginem do kompilatora, tylko stabilniejszym i lepiej udokumentowanym
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.