0

I was doing some reading on the following links:

Link 1

Link 2

Link 3

I notice that when using the factory pattern, all the examples I've seen use the no argument constructor in the factory. In the last link it's suggested that if the parameters grow, to consider using the builder pattern. I understand when and how to use the builder pattern, but the factory pattern is confusing to me. What happens if you have sub classes that have parameters, some of which are unique to the subclass? What do you do in this case?

Take this example:

Let's say you have the following abstract class:

public abstract class Client {

    private String clientID;
    private String clientFirstName;
    private String clientLastName;

    public Client(String ID, String firstname, String lastname)
    {
        this.clientID = ID;
        this.clientFirstName = firstname;
        this.clientLastName  = lastname;

    }
}

and the following sub-classes:

public class Domestic extends Client {
    public Domestic(String ID, String firstname, String lastname) {
        super(ID, firstname, lastname);

    }
}


public class International extends Client {

  private List<String> documents;

  public International(String ID, String firstname, String lastname, List<String> documents) {
    super(ID, firstname, lastname);

       this.documents = documents;

    }

Now, the arguments aren't enough to use the builder pattern are they? Is there anything wrong with simply doing this:

Client international = new International(id, firstname, lastname, documents); 

or

International internationalObj = new International(id, firstname, lastname, documents);
Community
  • 1
  • 1

1 Answers1

2

What happens when you decide you actually need a tree like:

Client
 |
 -- Domestic Client
 |
 -- International_client
    |
    |_ APAC Client
    |
    |_ EMEA client
    |
    |_ South America Client
    |
    |_ I'm not very creative, but imagine there are a bunch more.

Suddenly, when you need to instantiate the object, your code winds up like:

if (domestic) {
  client = new DomesticClient(...);
} else if (international) {
  if (apac) {
    client = new APACClient(); 
  } else if (emea) {
    client = new EMEAClient();
  } else if (sa) {
    client = new SouthAmericaClient();
  } 
...
}

As the number of possibilities grow, the likelihood you want this crud smattered around your codebase goes down. Maybe you don't even want the caller to need to know what sort of client they have, anyway. The abstractions should hide the different implementations, right? Why should I, as the client, need to know that John Smith customer ID 1234 is International. Maybe I want to be able to call something like:

 Client c = Client.ForCustomerId(id);

Or

 Client c = Client.Build(id, firstname, lastname, documents);

And magically get the appropriate client type, with no foreknowledge of the type of client they really are.

Many design patterns don't make a ton of sense in terms of utility when you're looking at a small problem. They shine when the problem becomes considerably more complex. E.g. IMO the builder pattern would not be too useful here as is -it's far more useful if you either A) have a TON of options, or B) have varying / optional options depending on different use cases. What you've described has a fixed set of small parameters.

Now, if you start adding a bunch of parameters - maybe you need a SSN for US customers or VAT information for EU customers, etc - maybe it makes sense to move to a Builder which takes these in, when you have them, and ultimately produces the object.

James
  • 8,512
  • 1
  • 26
  • 28