1
\$\begingroup\$

I have a class MassiveDTO that contains lists. At some point in the project, I need to generate an object of this class, that will contain some hardcoded data. I would like to know if there is a better way (or a design pattern) to populate those lists with known data.

With the method generateLists I populate them and I use them later on. Keep in mind, I need this class not to be static because I reuse it on the project.

MassiveDTO class

public class MassiveDTO {
 private List<String> company = new ArrayList<>();
 private List<String> partners = new ArrayList<>();
 private List<String> biodata = new ArrayList<>();
 public MassiveDTO(){}
 public MassiveDTO(List<String> company, List<String> partners, List<String> biodata) {
 super();
 this.company = company ;
 this.partners = partners ;
 this.biodata = biodata;
 }
 /** Getters and Setters **/
 public List<String> getCompany() {
 return company;
 }
 public void setCompany(List<String> company) {
 this.company = company;
 }
 public List<String> getPartners() {
 return partners;
 }
 public void setPartners(List<String> partners) {
 this.partners = partners;
 }
 public List<String> getBiodata() {
 return biodata;
 }
 public void setBiodata(List<String> biodata) {
 this.biodata = biodata;
 }
 public void generateLists(){
 /** Company**/
 company.add("X0788");
 company.add("X0192");
 /** Partners **/
 partners.add("X0081");
 /** Biodata**/
 biodata.add("X0913");
 }
}

My first idea is to create another static class that will extend MassiveDTO in order to reuse those lists, and that class will be static because I will only need it to contain those specific lists with their data.

asked Nov 5, 2019 at 12:26
\$\endgroup\$
7
  • 2
    \$\begingroup\$ Greetings, you should use data files for this, not code. This way you dont have recompile every time the static data changes. If you dont want this question closed, you should add the getters and setters, because otherwise this is not-working (or at least pointless) code. \$\endgroup\$ Commented Nov 5, 2019 at 12:48
  • \$\begingroup\$ @konijn You are absolutly correct, I just added them \$\endgroup\$ Commented Nov 5, 2019 at 12:51
  • \$\begingroup\$ What do you mean with "reuse it on the project"? It does not sound like something that would normally prevents fields from being static. \$\endgroup\$ Commented Nov 5, 2019 at 13:28
  • \$\begingroup\$ @TorbenPutkonen this class is being used as a request body for example \$\endgroup\$ Commented Nov 5, 2019 at 13:44
  • \$\begingroup\$ What's the class really being used for? MassiveDTO obviously isn't a good name. It's really hard to suggest alternatives without the real scenario. What if there's an entirely different, better approach to the overall problem? \$\endgroup\$ Commented Nov 6, 2019 at 1:25

3 Answers 3

2
\$\begingroup\$

So you need to separate the construction of that class from the class itself? This is the Factory Pattern.

Data class

Boil down to your DTO to ... well the data.

public class MassiveDTO {
 private final List<String> company;
 private final List<String> partners;
 private final List<String> biodata;
 /**
 * @see MassiveDTOBuilder
 */
 MassiveDTO(List<String> company, List<String> partners, List<String> biodata) {
 this.company = company;
 this.partners = partners;
 this.biodata = biodata;
 }
 ... getters only
}

Factory Pattern

Then have a second class, MassiveDTOFactory, that calls that constructor with suitable fixed values.

public class MassiveDTOFactory {
 public static MassiveDTO create() {
 return new MassiveDTO(
 List.of("X0788", "X0192"), // Here we use Java 9 immutable collections
 List.of("X0081"),
 List.of("X0913")
 );
 }
}

Fluent Builder Pattern

If you wish more flexibility on the values then a Fluent Builder is for you. Something like this:

public class MassiveDTOBuilder {
 private List<String> companies = new ArrayList<>();
 private List<String> partners = new ArrayList<>();
 private List<String> biodata = new ArrayList<>();
 public static MassiveDTOBuilder massiveDto() {
 return new MassiveDTOBuilder();
 }
 private MassiveDTOBuilder() {
 }
 public MassiveDTOBuilder withCompany(String... items) {
 for (String i : items) {
 companies.add(i);
 }
 return this;
 }
 public MassiveDTOBuilder withPartner(String... items) {
 for (String i : items) {
 partners.add(i);
 }
 return this;
 }
 public MassiveDTOBuilder withBiodata(String... items) {
 for (String i : items) {
 biodata.add(i);
 }
 return this;
 }
 public MassiveDTO build() {
 return new MassiveDTO(
 Collections.unmodifiableList(companies),
 Collections.unmodifiableList(partners),
 Collections.unmodifiableList(biodata)
 );
 }
}

Which can used like:

MassiveDTO m = massiveDto()
 .withCompany("X0788", "X0192")
 .withPartner("X0081")
 .withBiodata("X0913")
 .build();
answered Nov 11, 2019 at 18:02
\$\endgroup\$
0
1
\$\begingroup\$

OK, so what I understand, class MassiveDTO will be instantiated sometimes in your application, but those 3 lists can be static and won't change. So solution is create classes with static hard coded lists (3 classes) and just use static reference them in MassiveDTO:

public class MassiveDTO {
private List<String> company = CompanyDataHolder.COMPANY_LIST;
private List<String> partners = PartnersDataHolder.PARTNERS_LIST;
private List<String> biodata = BiodataHolder.BIODATA_LIST;
// you probably dont even need setters
public List<String> getCompany() {
 return company == null ? Collections.emptyList() : company;
}
public void setCompany(List<String> company) {
 this.company = company;
}
public List<String> getPartners() {
 return partners == null ? Collections.emptyList() : partners;
}
public void setPartners(List<String> partners) {
 this.partners = partners;
}
public List<String> getBiodata() {
 return biodata == null ? Collections.emptyList() : biodata;
}
public void setBiodata(List<String> biodata) {
 this.biodata = biodata;
}
}

And static lists (that can be compiled and won't change)

public final class BiodataHolder {
 public static final List<String> BIODATA_LIST;
 static {
 List<String> data = new ArrayList<>();
 data.add("Biodata 1");
 data.add("Biodata 2");
 // ...
 data.add("Biodata 100");
 BIODATA_LIST = Collections.unmodifiableList(data);
 }
}
 public final class PartnersDataHolder {
 public static final List<String> PARTNERS_LIST;
 static {
 List<String> data = new ArrayList<>();
 data.add("Partner 1");
 data.add("Partner 2");
 // ...
 data.add("Partner 100");
 PARTNERS_LIST = Collections.unmodifiableList(data);
 }
}
 public final class CompanyDataHolder {
 public static final List<String> COMPANY_LIST;
 static {
 List<String> data = new ArrayList<>();
 data.add("Company 1");
 data.add("Company 2");
 // ...
 data.add("Company 100");
 COMPANY_LIST = Collections.unmodifiableList(data);
 }
}
answered Nov 13, 2019 at 7:49
\$\endgroup\$
1
  • 1
    \$\begingroup\$ This seems a clear way to populate them, apprecite it. \$\endgroup\$ Commented Nov 13, 2019 at 9:07
0
\$\begingroup\$

There are following issues with such approach:

  1. If you call getBiodata() before generateLists() you will get empty list.
  2. User of this class should know internal implementation (generateLists() breaks encapsulation).
  3. If you use setters after generateLists() you will get the state without filled data.

I would suggest following:

  1. Create dedicated private method init() and use it in constructors.
  2. Remove setters, make the lists final.
  3. Return copy of the lists, it will protect state of the class from unexpected modifications.
  4. Add dedicated methods for lists modifications.

Have a look at the following code:

public class MassiveDTO {
 private final List<String> company;
 private final List<String> partners;
 private final List<String> biodata;
 public MassiveDTO() {
 this(new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
 }
 public MassiveDTO(List<String> company, List<String> partners, List<String> biodata) {
 super();
 this.company = company;
 this.partners = partners;
 this.biodata = biodata;
 init();
 }
 private void init() {
 company.add("X0788");
 company.add("X0192");
 partners.add("X0081");
 biodata.add("X0913");
 }
 public List<String> getCompany() {
 return new ArrayList<>(company);
 }
 public List<String> getPartners() {
 return new ArrayList<>(partners);
 }
 public List<String> getBiodata() {
 return new ArrayList<>(biodata);
 }
 public MassiveDTO addPartner(String partner) {
 partners.add(partner);
 return this;
 }
 public MassiveDTO addCompany(String comp) {
 company.add(comp);
 return this;
 }
 public MassiveDTO addBiodata(String bio) {
 biodata.add(bio);
 return this;
 }
}
answered Nov 9, 2019 at 9:34
\$\endgroup\$
1
  • \$\begingroup\$ I get it, but I expected something more..elegant I must say? Like a design pattern that handles data. \$\endgroup\$ Commented Nov 11, 2019 at 11:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.