1th: Consider replacing the constructor with a static factory method
Typically, we create an object to take the form of new, but there is also a method that is often used, and its name is called the static Factory method .
For example, the wrapper class Boolean for the basic type Boolean in Java takes this approach, with the following source code:
Public Static Boolean ValueOf (boolean b) { return (b? True:false); }
Of course, in addition to valueof this relatively low name, we commonly used getinstance (most common), Newinstance,gettype and so on.
Static factory methods have a lot of advantages over constructors.
The ① static Factory method has a name, and the constructor is fixed.
For example, the construction method of BigInteger returns a number. If you want to return a random prime number, a static method named Biginteger.probableprime will clearly make it clearer and easier to read.
② does not have to create a new object each time it is called.
This allows immutable classes to use pre-built instances, or to cache the built-in instances for reuse, thus avoiding the creation of unnecessary duplicate objects. For example, the Boolean.valueof (Boolean B) method in the previous example calls it, and it never creates an object.
③ It can return any subtype object of the original return type.
Here we have to mention the following simple factory model, everyone in the normal development of the use of very high frequency.
For example, there are physical heroes and spell heroes that want to get the corresponding heroes based on the incoming type.
public abstract class Hero {} public class aphero Hero {@Override public String toString () { return "spell hero" ; }} public class Adhero extends Hero {@Override public Span style= "color: #000000;" > String toString () { return "physical hero" ; }}
Using the static factory method, you can get to the specified subtype, which greatly increases the extensibility.
Public classherofactory {Aphero ap=NewAphero (); Adhero AD=NewAdhero (); PublicHero getheroinstance (String type) {Switch(type) { Case"AP":returnap; Case"AD":returnAD; default:return NULL; } }}
2nd: Consider using the builder when you encounter multiple constructor parameters
Static factories and constructors have one common limitation: they do not scale well to a large number of optional parameters.
Sometimes it happens that there are many attributes in a class, some are necessary, and some are optional. In this way, the normal construction method has to write a lot (because there are too many possibilities to create objects).
There is also a method that we use most often, that is, the construction method is used by default, each property is added the Get Set method (JavaBean). It's easy to create an instance, and the code is much clearer. Unfortunately, the JavaBean itself has a very serious disadvantage, because the construction process is divided into if all calls, there may be inconsistent state, resulting in multi-threaded operation is unsafe.
The builder method guarantees both security and readability. Let's take a look at an example (nutrition table on food):
Public classnutritionfacts {Private Final intservingsize; Private Final intservings; Private Final intcalories; Private Final intfat; Private Final intsodium; Private Final intcarbohydrate; Public Static classBuilder {//Required Parameters Private Final intservingsize; Private Final intservings; //No Required parameters Private intCalories = 0; Private intFat = 0; Private intCarbohydrate = 0; Private intSodium = 0; PublicBuilder (intServingsize,intservings) { This. servingsize =servingsize; This. servings =servings; } PublicBuilder Calories (intval) {Calories=Val; return This; } PublicBuilder Fat (intval) {Fat=Val; return This; } PublicBuilder Carbohydrate (intval) {Carbohydrate=Val; return This; } PublicBuilder Sodium (intval) {Sodium=Val; return This; } //note here, like JavaBean, the builder calls the build method to build a real object after setting a series of properties Publicnutritionfacts Build () {return NewNutritionfacts ( This); } } Privatenutritionfacts (Builder builder) {Servingsize=builder.servingsize; Servings=builder.servings; Calories=builder.calories; Fat=Builder.fat; Sodium=Builder.sodium; Carbohydrate=builder.carbohydrate; } }
On the client side, we can use this syntax similar to concatenating in jquery to create an object.
Public Static void Main (string[] args) { new Nutritionfacts.builder (8) . Calories (+). Sodium (carbohydrate).build (); }
In fact, it is equivalent to delegating the Nutritionfacts class to the static internal class builder for the ability to create objects. Also, because the static class itself is thread-safe, it avoids the javabean flaw.
Effective JAVA2 reading notes-Creating and destroying objects (i)