Factory classes

Personally, I never understood the idea of ​​factory classes, because it seems much more useful to just instantiate an object directly. My question is simple, in what situation is using the factory class template the best option, for what reason and to which class does the factory class look?

+43
java object oop factory
Jan 29 '13 at 4:02
source share
7 answers

The idea here is to separate the problems: if the code that uses this object also has enough information to create it, you do not need a factory. However, if there is some logic or configuration that you do not want the API user to think about (or bother with), you can hide it all (and encapsulate it for reuse) in the factory.

Here's an example: you want to access one of the services provided by Google App Engine. The same code should work both in the development environment (of which two versions, master-slave and high-availabilityabilty), and a completely different local development environment. Google does not want to tell you about the internal workings of its internal infrastructure, and you really do not want to know. So what they do is interfaces and factories (and several implementations of these interfaces for factories to choose from that you don't even need to know about).

+25
Jan 29 '13 at 4:06 on
source share

Here is a real live factory from my code base. It was used to create a samplers class that knows how to select data from some data set (it was originally in C #, so sorry any java faux-pas)

class SamplerFactory { private static Hashtable<SamplingType, ISampler> samplers; static { samplers = new Hashtable<SamplingType, ISampler>(); samplers.put(SamplingType.Scalar, new ScalarSampler()); samplers.put(SamplingType.Vector, new VectorSampler()); samplers.put(SamplingType.Array, new ArraySampler()); } public static ISampler GetSampler(SamplingType samplingType) { if (!samplers.containsKey(samplingType)) throw new IllegalArgumentException("Invalid sampling type or sampler not initialized"); return samplers.get(samplingType); } } 

and here is a usage example:

 ISampler sampler = SamplerFactory.GetSampler(SamplingType.Array); dataSet = sampler.Sample(dataSet); 

As you can see, this is not a lot of code, and it can be even shorter and faster to just do

 ArraySampler sampler = new ArraySampler(); dataSet = sampler.Sample(dataSet); 

than use factory. So why am I even worried? Well, there are two main reasons that are based on each other:

  • The first is the simplicity and ease of maintenance of the code. Let's say that in the calling code, the enum parameter is provided as a parameter. That is, if I had a method that should process data, including sampling, I can write:

     void ProcessData(Object dataSet, SamplingType sampling) { //do something with data ISampler sampler = SamplerFactory.GetSampler(sampling); dataSet= sampler.Sample(dataSet); //do something other with data } 

    instead of a more bulky design, for example:

     void ProcessData(Object dataSet, SamplingType sampling) { //do something with data ISampler sampler; switch (sampling) { case SamplingType.Scalar: sampler= new ScalarSampler(); break; case SamplingType.Vector: sampler= new VectorSampler(); break; case SamplingType.Array: sampler= new ArraySampler(); break; default: throw new IllegalArgumentException("Invalid sampling type"); } dataSet= sampler.Sample(dataSet); //do something other with data } 

    Please note that this monster must be written every time I need a sample. And you can imagine how fun it will change if, say, I added a parameter to the ScalarSampler constructor or added a new SamplingType . And this factory has only three options, imagine a factory with 20 implementations.

  • Secondly, it is code decoupling. When I use factory, the calling code does not know or should not know that a class named ArraySampler even exists. A class can even be resolved at runtime, and the call site will not be wiser. That way, I can change the ArraySampler class ArraySampler much as I want, including, but not limited to, deleting the class directly, if, for example, I decide that ScalarSampler should also be used for array data. I just would need to change the line

     samplers.put(SamplingType.Array, new ArraySampler()); 

    to

     samplers.put(SamplingType.Array, new ScalarSampler()); 

    and it will work magically. I do not need to change one line of code in the calling classes, which could number hundreds. In fact, the factory allows me to control what and how the selection occurs, and any changes to the selection are effectively encapsulated within the same factory class that interfaces with the rest of the system.

+47
Jan 29 '13 at 8:33
source share

Personally, I use the factory pattern when the implementation of the interface is unknown at runtime or can be made dynamic.

This means that as a developer I work against a well-known interface with an instance of an object, but I am not interested in how the implementation works.

Take for example. You can use the factory template to provide you objects from the database. You do not care if this database is a flat file, a local / single user database, a server database or a web resource, only that the factory can create and manage these objects.

I would not want to write implementations for each of these cases: P

+4
Jan 29 '13 at 4:08
source share

From Joshua Bloch's effective Java book, partially rewritten by me:

1) Static factory methods ( SFM ), unlike constructors, have names.

 public static ComplexNumber one () { return new ComplexNumber(1, 0); } public static ComplexNumber imgOne () { return new ComplexNumber(0, 1); } public static ComplexNumber zero () { return new ComplexNumber(0, 0); } 

2) It is not necessary to create a new object every time you call SFM

 public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } 

3) SFM can return an object of any subtype of return type.

4) SFM reduce the volume of creating instances with a parameterized type.

 public static <K, V> HashMap<K, V> newInstance() { return new HashMap<K, V>(); } Map<String, List<String>> m = HashMap.newInstance(); 
+3
Jan 29 '13 at 4:43
source share

To complement Tilo’s answer, suppose you have an object that has only logical value as a constructor: it will be a complete departure to build each time, because it has only two possible values.

In this case, you can create static factory methods. The Java Boolean class is an example: Boolean.valueOf() .

0
Jan 29 '13 at 4:08
source share

Factory in itself does not show its beauty so easily. This is when you combine it with other templates, when you see real advantages, for example, if you want to use a decorator template, directly creating an object can add an additional link to your code. As the OOP teacher says, the connection is bad), so if you were to create an instance of the decorated object and did not want to increase the grip, you can use the factory.

0
Jan 29 '13 at 4:09
source share

You can refer to wikipedia , but the basic idea of ​​most design patterns is to introduce some abstraction to achieve better maintainability and / or reuse. Factory method template is no exception, what it does is to abstract the complexity of creating from code.

For a simple case, it makes no sense to use the Factory template, just new enough. But when you need more flexibility or functionality, this template can help.

For example, if a new instance is not required, a static Factory valueOf(boolean) usually better than new Bealean(boolean) because it avoids creating unnecessary objects. Factory method template is also known as Virtual Constructor . As you know, polymorphism is one of the key features of OOP, but the constructor cannot be polymorphic, this drawback can be overcome using the Factory method template.

In essence, instantiating an object directly (usually via new ) is hardly a concrete implementation, while the Factory method template escapes a mutable implementation using a stable interface > (not limited to interface in Java), pushing the object creation logic behind some abstraction so that provide more convenient and reusable code.

As a final word, to fully understand the benefits of the Factory method template and other design patterns, you need to understand the essence of OOP, including data abstraction , polymorphic abstraction, and SOLID .

0
Jan 29 '13 at 4:10
source share



All Articles