1

I am working on some code that needs to abstract the creation of an HttpClient. The Http Client will be an instance of the org.apache.http.client.HttpClient. The configuration of the Http Client will vary based on configuration information (i.e. is it a post/get request,basic auth, maybe some headers, etc).

To implement this I was thinking of using the Factory design pattern which would abstract the creation of the Http Clients;however, I wanted to know if the Builder pattern would be a better alternative.

I have looked at a couple of posts on this topic (see below) and it seems that the main difference is the complexity required in creating the instance. In one of the posts below it says that a Factory is a wrapper around constructors and when the factory creates the object everything should be done on one line.

Question: 1. If the creation of the HttpClient needs to do some additional steps (i.e create an instance, set some parameters, etc) am I breaking the Factory pattern and should use a builder?

Similar posts:

  1. What is the difference between Builder Design pattern and Factory Design pattern?

  2. https://myjavalatte.wordpress.com/tag/builder-pattern-vs-factory-pattern/

  3. Difference between Abstract factory and builder?

Community
  • 1
  • 1
  • As seen on the first question: "Builder focuses on constructing a complex object step by step.". So builder is the best fit for your problem. – andrucz Feb 15 '16 at 17:35
  • 1
    @andrucz You are right too, i would suggest to use a combination of both. Hey, noone said you cant combine patterns. :D – Grim Feb 15 '16 at 17:38
  • What exactly are you trying to abstract? The different implementations of the HttpClient interface? If that's the case why not use the interface instead of the concrete class for the logic and for construction use the already existing [httpclient builder](https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/index.html)? – Gideon Feb 15 '16 at 19:59
  • It really depends on the level of abstraction that you need... – plalx Feb 15 '16 at 20:08
  • Everyone, Thanks for the comments. This is exactly what I was looking for. As I mentioned I had read a couple of post on the different types of creational patterns and was just trying to get some of the subtle differences on the implementations. Thanks again to everyone who provided a response. It help give me some clarification. Thanks – Shannon Lal Feb 16 '16 at 18:30

3 Answers3

0

The abstract-factory pattern differs from the factory pattern. What patterns to use must be dictated from the focused design-principles for your unit of work.

Answer 1:

HTTPClient handling can be very complex, use cookies or not, follow redirects, send referee or not, what mimetype is requested...

The builder-pattern gives the control about the handling away. The abstract-factory pattern would be better because:

  1. You follow the SRP and you knew where to modify the code.
  2. You follow the OAOO and have only one position where to change the HTTPClient on bugs or advantages.
Grim
  • 1,938
  • 10
  • 56
  • 123
  • +1 for factory or abstract factory. Builder doesn't really help here, and would probably result in SRP violation – erosb Feb 15 '16 at 17:36
0

There will be a lot of configuration possibilities, so builder pattern is the best fit for your problem. Factory pattern is more recommended when creation is made in one step.

Note that http-client has a HttpClientBuilder implementation: http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html

Internally, you can mix both patterns. Example:

new HttpClientBuilder()
      .setSomeParameter(MyEnum.VALUE)
      .build();

Then when building concrete HttpBuilder, you can use a factory to create some instance based on someParameter value:

public void HttpClient build() {
    HttpClient client = ...
    SomeAdditionalClass instance = SomeAdditionalClassFactory.create(this.someParameter); // one-step creation
    client.setSomeAttribute(instance);
    ...
    return client;
}
andrucz
  • 1,971
  • 2
  • 18
  • 30
-1

First of all, to be clear about this: There is nothing like a best Design Pattern. There is only Design Patterns that match your needs and Design Patterns that don't match. It always depends on the situation. Thus, I will provide a description of each pattern that helps to identifying the useful ones.

Solution 1 - Builder constructing a single instance

The builder pattern is used to build complex products with many different possible configurations. We can further divide this pattern, however you will often see a mix of these:

Expression Builder

This type of Builder is used to provide a nice API to the programmer using the builder. A common example is the implementation of a fluid interface. Essentially, the builder provide an internal DSL to the programmer.

Construction Builder

This type of Builder is used to encapsulate a complex construction algorithm. As opposed to the Expression Builder, it often has a very simple interface.

Solution 2 - Builder constructing multiple instances

This is the most complex and flexible solution. It uses a builder pattern to build a factory. The factory will create instances as configured by the builder. So you have the flexibility of the builder pattern but at the same time you can create multiple instances from a single configuration.

Solution 3 - Factory

If you have exactly one configuration to build your product, just go for a simple factory. The factory alone knows how to build a new instance.

Solution 4 - Abstract Factory

If you have a fixed set of configurations to build the product, you can use the abstract factory pattern by implementing a new concrete factory for each of the configurations. For example:

  • use basic auth and a given header
  • use no auth and no header

Solution 5 - Factory Methods

This is quite similar to the Factory and Abstract Factory pattern: You have a fixed set of configurations. However, as opposed to these patterns, you do not implement each factory as a class but as a method.

Note, that this is not that different from the Abstract Factory pattern, since Java 8 comes with lambdas and the Supplier<T> interface. This enables you to pass any factory method as a supplier into other objects, effectively making it an abstract factory.

Summary

In general, the difference between the builder and the factory patterns is, that each factory knows exactly how to build its product. It might require additional parameters to do so. However, a single builder can be used to create products with very different configurations. It is also common practice to encapsulate complex construction algorithms in a builder.

So what should I use?

Without knowing the context where you want to use the Factory/Builder, it is nearly impossible to answer this question. Also, you will nearly never see pure patterns in real code. Patterns are just an idealized form to communicate about abstract design ideas. What I mean by that is that there is often a mix of different patterns.

One example for this is the builder that constructs the factory: You can also let the builder directly construct multiple product instances, however the idea is easier to communicate by using the term "factory".

Also, the Construction Builder and Expression Builder will often be mixed in code, but it is good to think about them as separate concepts.

The same is true for the Builder and Factory patterns. Most of the time you will start with a simple Factory Method. Over the time you add more Factory Methods. Also, the existing Factory Methods will become more complex. At some point you will start to extract the Factory Methods to separate Factory classes. As a Factory becomes more complex, it slowly turns into a Construction Builder.

Example

The class DocumentBuilderFactory is a good example for how patterns are used in real code: The name implies that it is a Factory that creates a Builder that can build xml documents. Lets look further into this:

DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(...)

The class DocumentBuilderFactory really contains two factories: The static methods are factory methods creating products of the type DocumentBuilderFactory. An instance of this class produces products of the type DocumentBuilder. The product of a DocumentBuilder is of the type Document.

DocumentBuilderFactory

Now lets have a look which pattern does and does not match the class DocumentBuilderFactory and why. First, the class provides two static Factory Methods to create an instance of itself. These methods also kind of implement the Abstract Factory Pattern: You can choose which concrete factory should be created by providing the name and class loader of it.

Now, that we are done with the static factory methods, lets have a look at an instance of the class DocumentBuilderFactory. The name implies that this is a factory. Indeed, as we saw above, it is an implementation of the abstract factory interface given by the type DocumentBuilderFactory. However, one can argue that this is too complex to be a factory, since it contains quite a few methods to pass configuration parameters, which are used to create the product. This type of interface would better match the Expression Builder pattern.

Thus, this class is a great example for my statement that you will often find a mix of patterns in real code. After all, this class is just a class. A class that can create instances of several different types by using a set of configuration options. The point of naming it like well known patterns is to give the programmer an idea about what the class is doing. Nothing more and nothing less.

DocumentBuilder

To me, this class can be seen as a Construction Builder: The parse() method performs a complex operation and the class itself has a quite simple interface. However, it is also a simple factory when using the newDocument() method: It does not perform a complex operation.

Again, this is an example of a class that mixes the implementation of multiple patterns.

Stefan Dollase
  • 4,530
  • 3
  • 27
  • 51
  • What is it with the downvotes? At least say what is wrong with the answer. – Stefan Dollase Feb 15 '16 at 18:41
  • I am not the downvoter and think your collection gives a good overview. I miss the factory pattern, yes you had the abstract-factory-pattern and the static-factory-method-pattern but...yes i miss the factory-pattern. What do you mean by "you will nearly never see pure patterns in real code"? – Grim Feb 18 '16 at 19:36
  • Thanks for the feedback. I added more details about the builder pattern, the factory, a summary and a usage hint. – Stefan Dollase Feb 18 '16 at 23:28
  • Hm, i am now unhappy with the factory and abstract factory desciption. If you look at `javax.xml.parsers.DocumentBuilderFactory` you will notice that 1. its a Singleton 2. a abstract-factory-pattern for Objects (implementing the builder-pattern by the way). This abstract-factory-pattern can be configured so the final configuration is not-fixed. It is not the nature of a factory to be fixed in configuration. – Grim Feb 19 '16 at 06:58
  • I added this class as an example. Also, I do not see the Singleton pattern there. It always creates a new instance of itself when you call newInstance(), as described in the [Javadoc](https://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html#newInstance--). – Stefan Dollase Feb 19 '16 at 20:26