[Negative tive Java Distilled] Item 2 when there are multiple parameters in the constructor, consider the builder Mode

Source: Internet
Author: User
Tags sodium

I have read this book about objective Java Distilled: "objective Java" intermittently for nearly two times. The content in this book is quite deep and is very helpful for improving the quality of engineering code. I plan to organize a series slowly. The reason why I name it objective Java Distilled is to organize the essence of this book as much as possible to facilitate review and use. After all, my memory is limited and many things are often forgotten. Of course, it would be better if it could help you. Outline of this article: The influence of too many parameters on static factory methods and constructor methods the JavaBean Mode and Its drawbacks the use of the builder mode the generalized builder mode usually has some entity classes in actual engineering, these entity classes usually have a number of fields to save various related states. Some statuses must have values, while others are optional. The instantiation of such entities is usually completed by a constructor that contains all required States, and some setters methods are provided for other optional states, it is used to set the optional status after initialization. This mode has gradually become a convention and will be used in many frameworks. For example, in An ORM framework such as Hibernate, When retrieving records from a database table, the records are converted to Java objects in this form. Once you get used to this method, you will not feel that this method is inappropriate. However, you still need to consider the absence of framework support. If you need to write your own code to instantiate many objects, there is no doubt that there is much room for improvement in the above constructor initialization method combined with setters. Too many parameters affect static factory methods and constructor methods. For more information about the concept of static factory methods, see Item 1. Too many parameters, especially too many optional parameters, have adverse effects on static factory methods and constructor methods. For example, there are five parameters, where a and B are mandatory and c, d, and e are optional. To create this object, without considering setters, the number of required constructor methods (static factory methods) is: 1 + 3 + 3 + 1 = 8, as shown in the following code: only the number of required parameters is: 1, that is, the number of constructor (a, B) with an optional parameter: 3, that is, constructor (a, B, c) constructor (a, B, d) and constructor (a, B, e) Number of two optional parameters: 3, constructor (a, B, c, d) constructor (a, B, c, e) and constructor (a, B, d, e) Number of all optional parameters: 1, that is, constructor (a, B, c, d, e) Telescoping Constructor mode. The preceding declarative constructor (or static factory method) is called Telesco Ping the Constructor mode, that is, add necessary parameters first, and then gradually increase the number of optional parameters until all parameters are available. This mode can work, but there are also many drawbacks. The first thing is that the scale of the constructor is too large. When there are only five parameters and three of them are optional, up to eight constructor methods (or static factory methods) are required. When the number of optional parameters continues to increase, the number of required constructor methods is explosively increasing. In addition, when the types of optional parameters are the same, it is easy to mistake the parameter location. This type of error is hard to prevent. Because of the same type, there will be no errors during compilation, and various inexplicable problems will occur during runtime. The main idea of the JavaBean Mode and Its drawbacks is to provide only one non-parametric constructor method, and then set the necessary and optional fields through the setters method. Its main drawbacks include: the code is lengthy. When many fields need to be set, it is more obvious that every field needs to explicitly call its setter method. The possible inconsistency in the concurrency environment is that every field needs to call the setter method to set its value, so without using the synchronization mechanism, it is not guaranteed that all fields can be set as atomic operations. Of course, the atomicity of setup operations can be ensured through various synchronization mechanisms, but this will sacrifice some performance. The object Class cannot be declared as Immutable Class because setters is introduced in the Class, which violates the basic requirements of the Immutable Class, that is, after the object is created, any value in the object is no longer variable. Variable classes have almost no risks in a single-threaded environment, but there may be various risks in a concurrent environment. This will be discussed in future concurrency related Items. The setters method may damage the immutable constraint (Invariants). If there is an immutable constraint between several fields in the object class, the setters method may damage the constraint when assigning values, this brings hidden risks to the program running. The compliance of immutability constraints is very important in the concurrency environment. This concept will be discussed in the Items related to post-order concurrency. Whether using the builder mode is Telescoping Constructor mode or the JavaBean mode, the reason for using them is that Java only supports Positional Parameters ), named Parameters is not supported ). In other languages, such as Python, both modes are supported. The typical Python method Signature: def method (* args, ** kwargs) clearly reflects this point, here, args represents the location parameter, while kwargs is the naming parameter. Unfortunately, Java does not have built-in language features to support naming parameters, but by using the builder mode, you can imitate this line: directly reference the example about nutrients in objective Java: [java] // Builder Pattern public class NutritionFacts {private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; public static class Builder {// Required parameters private final int servingSize; private final in T servings; // Optional parameters-initialized to default values private int calories = 0; private int fat = 0; private int carbohydrate = 0; private int sodium = 0; public Builder (int servingSize, int servings) {this. servingSize = servingSize; this. servings = servings;} public Builder calories (int val) {calories = val; return this;} public Builder fat (int val) {fat = val; return this;} pu Blic Builder carbohydrate (int val) {carbohydrate = val; return this;} public Builder sodium (int val) {sodium = val; return this;} public NutritionFacts build () {return new NutritionFacts (this) ;}} private NutritionFacts (Builder builder) {servingSize = builder. servingSize; servings = builder. servings; calories = builder. calories; fat = builder. fat; sodium = builder. sodium; carbohydrate = bui Lder. carbohydrate;} the code for the construction process is: [java] NutritionFactscocaCola = new NutritionFacts. builder (240, 8 ). calories (100 ). sodium (35 ). carbohydrate (27 ). build (); The above uses chained assignment, which looks more natural than setters, and has less code redundancy. The method of chained assignment is similar to the scenario where named parameters are used for assignment. The preceding optional parameters, such as calories, sodium, and carbohydrate, can be regarded as keys, and the subsequent parameters are values. The key point of a chain operation is that the return type of each method in the chain is the type itself. Let's take a look at how the builder mode overcomes the shortcomings of the preceding Telescoping Constructor mode and the JavaBean mode: the Constructor mode is too large. Obviously, after using the builder mode, there are only two constructor methods. One is the common constructor of the builder, and the other is the constructor that declares the object class as private, it can only be called through the builder instance. Therefore, there is only one constructor actually exposed to external code. The problem of confusing parameters in TC mode is that the number of required parameters is limited, while the number of optional parameters is very large. For example, the constructor in the above object has only two required parameters, because it can avoid declaring any optional parameters in the constructor method, the builder mode greatly reduces the problem of parameter obfuscation. If there are only two parameters that can be obfuscated, it will be okay ...... In the JavaBean mode, the chained value assignment method can be used to reduce the length of the constructed code. The non-atomicity of the construction process in the JavaBean mode when the builder mode is used to construct an object, the object can be normally accessed only after the builder instance build method is called, in addition, after the build method is called, all fields will be initialized normally. If setters is not used, the object initialization is incomplete. In the JavaBean mode, the mandatory declaration class is non-mutable. From the above sample code, we can see that all the domains of the object class are declared as private final. They do not have the setters method, that is, once the object is initialized, its fields cannot be changed. This makes the entity class an immutable class, so that the type can be used more securely and efficiently in the concurrent environment. In the JavaBean mode, the setters method may break the immutable constraint, which can be controlled in the build method of the builder object. Because the build method is responsible for instantiating object classes, some parameters can be checked before the entity classes are instantiated. If immutable constraints are not met, an exception can be thrown according to the scenario, if no custom exception exists, IllegalStateException is thrown. The generalized builder mode in Item 1 mentions that the static factory method is somewhat similar to the simple factory mode. This is achieved by declaring the return value of the static factory method as the parent type. With generics, the builder mode and the abstract factory mode can be integrated through the following interface: [java] // A builder for objects of type T public interface Builder <T> {public T build ();} Why is this integration with the abstract factory model, instead of integrating with the simple factory mode, this is because the interface defined above allows the constructed actual object to change in at most two dimensions. First, T itself is a dimension. here T is just a placeholder (placeholder), which can represent any type, including the interface type. If T is an interface type or a parent class at a class level, the second dimension is enabled because it represents a series of objects. In this way, the following things are similar to the simple factory model. Similarly, if the T type is actually a specific class, such as the aforementioned NutritionFacts, then the abstract factory model degrades to a simple factory model. In the preceding example, the Builder declaration should be changed to: publicclass NutritionFacts {...... Public static class NutritionFactsBuilderimplementsBuilder <NutritionFacts> {......}} Reference Item 2 in objective Java: when there are too many parameters in the constructor or static factory method, especially when there are many optional parameters, consider using the builder mode. It is easier to read and concise than the Telescoping Constructor mode. It is also safer than the JavaBean mode.

Related Article

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.