Static Factory Method vs Constructor

Source: Internet
Author: User
Tags integer generator

I've already covered some of the builder pattern, which is a useful way to instantiate a class that contains several attributes (optional), and the benefit is easier to read, write, and maintain client-side code. Today, I will continue to introduce object creation techniques.

In my opinion, the following class is a very useful example. There is a randomintgenerator class that produces an integer of the random int type. As shown below:

public class Randomintgenerator {private final int min;private final int max;public int next () {...}}

This generator receives a maximum and a minimum of two parameters and generates a random number in between. Note that two properties min and Max are final decorated, so they must be initialized. They can be initialized when they are defined or by constructors. The constructor is initialized by the following:

Public randomintgenerator (int min, int max) {    this.min = min;    This.max = max;}

Now, we're going to provide a feature where the client sets a minimum value and then produces an integer between this value and Integer.max_value. So we added a second constructor:

Public randomintgenerator (int min) {    this.min = min;    This.max = Integer.max_value;}

So far, everything is fine. However, we also provide a constructor to set a maximum value, and then produce an integer between Integer.min_value and the maximum value. We add a third constructor as follows:

Public randomintgenerator (int max) {    this.min = Integer.min_value;    This.max = max;}

If you do this, a compilation error will occur:Duplicate method Randomintgenerator (int) in type Randomintgenerator. There was a mistake? There is no doubt that the problem is that the constructor has no name. Therefore, a class has only one constructor for a specific method signature. Similarly, you cannot define the same method signature (return value, name, parameter type, and number are the same) two methods. That's why when we try to add the constructor randomintgenerator (int max), we get the above compile error because we already have a constructor randomintgenerator (int min).

How do we deal with situations like this? Fortunately there are other ways to use the: static Factory method , which returns an instance of a class by using a simple public static method. You may have used this technique in unconsciousness. Have you ever written boolean.valueof?, like this:

public static Boolean valueOf (Boolean b) {    return (b? True:false);}

Apply a static factory to the Randomintgenerator class to get

public class Randomintgenerator {    private final int min;    private final int Max;    Private Randomintgenerator (int min, int max) {        this.min = min;        This.max = max;    }    public static randomintgenerator between (int max, int min) {        return new Randomintgenerator (min, max);    }    public static randomintgenerator Biggerthan (int min) {        return new Randomintgenerator (min, integer.max_value);    } Public    static randomintgenerator Smallerthan (int max) {        return new Randomintgenerator (Integer.min_value, max);    }    public int Next () {...}}

Notice that the constructor is private decorated to ensure that the class can only be initialized by a static factory method. And when you use Randomintgenerator.between (10,20) instead of new Randomintgenerator (10,20) to produce integers, your intentions are clearly expressed. It is worth noting that this technique differs from the factory design pattern of Gang of four. In addition, any class can provide a static factory method alternative to the constructor. So what are the advantages and disadvantages of this technology? We have already mentioned the first advantage of the static factory approach: The static Factory method has a name. Here are two direct benefits:
1. We can provide a meaningful name to the static method
2. We can give static methods a few constructors with the same parameter type and number of arguments, which cannot be done in a traditional constructor
Another advantage is that, unlike a constructor, a static factory method does not need to create a new object each time it is called. It is useful to use immutable classes (immutable class) to produce constant objects for common values and to avoid unnecessary duplication of objects. The above-mentioned boolean.valueof perfectly illustrates this point. Note that this static method returns both the immutable Boolean object true or False.
A third advantage is that the type of the return object of a static factory method can be any subtype of the return type. This gives you the freedom to change the return type without worrying about the possibility of affecting the client code. In addition, you can hide the implementation class and build an interface-based API (Interface-based API). Illustrated by an example.
Remember the first Randomintgenerator class? We made him a little more complicated. Suppose we now want to provide a random generator that not only produces an integral type, but can also produce other data types such as String, double, or long. These generators will have a next () method that returns a specific type of random object, so we can first define an interface such as:

Public interface Randomgenerator<t> {    T next ();}

The first implementation class for Randomintgenerator is as follows:

Class Randomintgenerator implements randomgenerator<integer> {    private final int min;    private final int Max;    Randomintgenerator (int min, int max) {        this.min = min;        This.max = max;    }    Public Integer Next () {...}}

A generator of type string such as:

Class Randomstringgenerator implements randomgenerator<string> {    private final String prefix;    Randomstringgenerator (String prefix) {        this.prefix = prefix;    }    Public String Next () {...}}

Notice that all classes and constructors of classes are defined as package private scopes (the default visible range). This means that client code other than this package cannot create instances of these generators. So what do we do? Tip: It starts with "static" and ends with "methods". Consider the following class:

Public final class Randomgenerators {    //suppresses default constructor, ensuring non-instantiability.    Private Randomgenerators () {} public    static final randomgenerator<integer> getintgenerator () {        return New Randomintgenerator (Integer.min_value, Integer.max_value);    }    public static final randomgenerator<string> Getstringgenerator () {        return new Randomstringgenerator (');}    }

The Randomgenerators class has become a non-instantiated tool class, and it is no different from the static factory approach. In the same package, different generator classes can efficiently get and instantiate these classes. But the interesting part came up. Note that these methods only return the Randomgenerator interface, which is what the client code really needs. If it gets a randomgenerator it will know to call next () and then get a random integer.
Let's say we write a new, efficient integer generator next month. As long as the new class is implemented Randomgenerator we replace the return type in the static method, then all the client code magically uses the new implementation.
Classes like randomgenerators are fairly common in JDK and third-party class libraries. You can see many examples in collections (Java.util) and lists, sets or Maps (in guava). The naming habit is the same: if you have an interface named type, then the static method name in the non-instantiated class is types.
The last advantage is that the static factory is an instantiation of the parameter class very concise. Have you ever seen a code like this?

map<string, list<string>> map = new hashmap<string, list<string>> ();

You repeat the same argument two times in the same line of code! If the assignment on the right can be inferred from the left, it would be an elegant approach. You can use static methods. The following code is taken from the guava ' s Maps class:

public static <k, v> hashmap<k, v> newhashmap () {  return new hashmap<k, v> ();}

So now our client code becomes the following:

map<string, list<string>> map = Maps.newhashmap ();

It's pretty classy, right? Such a capability is assumed to be type inference (type interface). It is worth mentioning that Java7 introduces type inference by using the square bracket operator (diamond operator). So, if you use Java7 you can have examples like:

map<string, list<string>> map = new hashmap<> ();

The main disadvantage of a static factory is that a constructor with no public or protected in the class cannot be inherited. But in fact, in some cases this is a good thing, because developers are encouraged to use combinations rather than inheritance (favor composition over inheritance).
In general, the static factory approach offers many advantages, and when you use it, the only disadvantage is not actually a problem. So, evaluate if your class is more suitable for static factories and refuse to provide public constructors eagerly.

original articles, reproduced please specify: reproduced from the Concurrent programming network –ifeve.com This article link address: static Factory Method vs Constructor

Static Factory Method vs Constructor

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.