About constructors
I got a question about Constructors.I think constructors are all just our convenience instead of setter methods,right? So for an object , the properties you think important(such as required fields in a webform)are passed as parameters into constructor.
Is there any criteria that these many number of parameters should be pass开发者_JAVA百科ed into constructor? Please elaborate on these points and as well as any points about constructors.
Edit:Sorry about the way i asked question.Yes,we create an object with constructor and we assign values with setters but my question is about the comparison between default constructor with setters and constructor with explicit parametrs.
No, it's not just a convenience instead of setters. In particular, a constructor will only be called once. Using constructor parameters, you can create immutable types which are given their values at construction time - that wouldn't be possible with setters.
It's generally not a great idea to have huge numbers of parameters, whether to a constructor or a normal method. If you find you have a lot of parameters, you may want to create a type representing all the related ones - that type may have a bunch of getters/setters. See ProcessStartInfo
for an example of this.
I see it this way:
You pass the parameters in a constructor that are required in order to create an object that is in a 'valid' state.
For your example: I would not pass 'required fields in a webform' to the instance of the class that is filled up with those values.
You have to call setters on an object, and the constructor creates that object. Without a constructor invocation, you'll have no object to call upon.
Re. the number of parameters. If you have a sizable number of parameters, that suggests:
- related parameters might be composable into objects themselves. e.g. a start date and an end date into a TimePeriod object
- that object has too many responsibilities, and should be decomposed further
Check out the Factory pattern and Builder pattern for some alternatives re. creating objects.
A further note re. constructor parameters and setters. In Java and C#, the parameters passed into the constructior can be used to initialise fields once only, and the fields are immutable from that point on (unlike when you set these via setters). This has great benefits for code reliability (at some cost of object immutability).
Constructors are used to initialise a class. You should pass as many parameters as are required to define your class into the required initial state.
Note that you can also overload a constructor.
If you have some non-optional, and many optional parameters, and you want to avoid looong parameter lists in constructors (which can be very error-prone, especially if the parameters are of the same type), you should favor the use of the
Builder pattern
instead.
You can also consider the use of the Factory pattern for object creation.
I think you should pay more attention to where the objects are being deployed when deciding how to create them. I try to summarize some points that help when choosing which method to use for filling object fields, i.e. constructor or setter methods:
State: By state, I mean the value of all fields of an object in a snapshot of runtime. When developing an application, keeping track of object state is important especially if an object is going to be accessed in multiple threads. Even in single-thread programming, objects may be modified in different methods and classes especially in languages such as Java that passes all objects by reference. Setting the state once and for all the lifetime of an object (in the constructor) and avoiding setters (called immutable pattern) makes programming, especially concurrent programming, really easier. But pay attention that this approach increases object modification cost because all the fields should be copied into a new instance on each modification; for example in Java, compare String (which is immutable) to StringBuilder and StringBuffer (which are stateful). String is thread-safe and easy-to-use but costly for long string creation, while StringBuilder is not thread-safe but fast in concatenating small strings. Meanwhile, StringBuffer is both stateful and thread-safe but costly in every method call because its methods that are synchronized (It means: do not make a stateful object thread-safe when it is not necessary in most of the use cases). So, as a general hint: use constructors (and immutable pattern) for objects which are accessed in multiple threads and use setters for local objects and fields which are under more control.
Injection: When we are using a dependency injection framework such as Spring or Guice, the framework makes one method more preferable than the other. For example, spring encourages setter injection more than constructor injection. Spring constructs the objects (beans) mostly using default constructors and then injects the dependencies using setter methods. Then Spring calls the init (PostConstruct) method for you. So, you can do whatever initialization you want in this method with the dependencies in-place. In contrast, Guice encourages constructor injection as its best practice.
Beauty of Code: Not only having a long list of parameters in a constructor is not beautiful, but also if many other constructors should be overloaded to support multiple optional parameters, these constructors may clash because of having same parameter types. Therefore, using setters is more effective if many of the fields are optional. But I think even in this case, the object usage scenario is more important. Long list of parameters can be resolved by grouping them in other classes, as other developers have suggested here.
To new or To Delegate: Whenever you are going to new an object whether using constructor or setter methods to fill the fields, it is a good practice to think if it may be needed someday that someone else pass (inject, create) it here. This leads to the Factory design pattern which is helpful especially when developing tools and libraries.
精彩评论