Java constructor with large arguments or Java bean getter/setter approach

后端 未结 18 2076
清歌不尽
清歌不尽 2020-12-12 21:29

I can\'t decide which approach is better for creating objects with a large number of fields (10+) (all mandatory) the constructor approach of the getter/setter. Constructor

相关标签:
18条回答
  • 2020-12-12 22:03

    This two patterns are useful to think about this kind of scenario:

    • Introduce Parameter Object from Fowler's "Refactoring".
    • Replace Constructors with Creation Methods, from Joshua Kerievsky's book, "Refactoring to Patterns".
    0 讨论(0)
  • 2020-12-12 22:06

    IMHO, you should pass everything that is needed for an object to be valid according to your business logic in the constructor.

    If the argument list is lengthy, you could create an object that contains the arguments and pass that.

    0 讨论(0)
  • 2020-12-12 22:07

    This is pretty hard to answer in the abstract. What really needs to be done is to look at those ten parameters and see what they are. I see these as the key questions:

    • Can some of them be combined into higher level "value" objects? For example, variables X and Y can be combined into Point. We had lots of situations like this within a cargo routing program where all fields were modeled as primitive strings. Introducing a few higher level concepts really helped make it readable.
    • Can some of the parameters be "defaulted" to certain values?
    • Are they really all independent, orthogonal concepts? I've worked on lots of systems and never seen this to be true. If not, there is some thinking to do about these.
    0 讨论(0)
  • 2020-12-12 22:09

    Are there variations of the class that might take fewer arguments, or is there just one and it has ten properties?

    Is the object meant to be immutable?

    Personally, I don't see anything wrong with large constructors, especially if there's only one constructor, and all the properties are final too.

    0 讨论(0)
  • 2020-12-12 22:09

    If all parameters are actually required, and you're not using Spring to instantiate the bean, I would definitely go with a constructor with 10 parameters. It's crystal clear that way that all parameters are, in fact, required.

    If you do you Spring (perhaps occasionally) to create the bean, or you don't really like having a lot of temporary variables in the method which constructs that bean, you can also use getters and setters. If you also implement a validate method to check if the object is correct you should not have problems.

    The validate method works best however if you use it consistently; perhaps by having a Validatable interface. It fits very well in a workflow if it's part of the programming style. If there are only one or two classes in which this paradigm is used it's probably not worth it. You'll forget to call validate() anyhow someday, somewhere.

    If you're not using a validator approach and dislike the constructor (though I wouldn't know why, that's what it's for) you can always fall back to the Builders mentioned by the others.

    For what it's worth; if you have 10 required arguments, and you can not group them logically, you may just have mixed to many different concepts in one class; in that case it might be even better to take a good, hard look at your design and refactor a bit.

    0 讨论(0)
  • 2020-12-12 22:12

    I would implement the builder pattern like this:

    package so1632058;
    
    public class MyClass {
      private final String param1;
      private final String param2;
    
      MyClass(Builder builder) {
        this.param1 = builder.param1;
        this.param2 = builder.param2;
      }
    
      public String getParam1() {
        return param1;
      }
    
      public String getParam2() {
        return param2;
      }
    
      @SuppressWarnings("hiding")
      public static final class Builder {
        String param1;
        String param2;
    
        public Builder param1(String param1) {
          this.param1 = param1;
          return this;
        }
    
        public Builder param2(String param2) {
          this.param2 = param2;
          return this;
        }
    
        public MyClass toMyClass() {
          return new MyClass(this);
        }
      }
    }
    

    And then have the following code to use it:

    package so1632058;
    
    public class Main {
    
      public static void main(String[] args) {
        MyClass.Builder builder = new MyClass.Builder();
        builder.param1("p1").param2("p2");
        MyClass instance = builder.toMyClass();
        instance.toString();
      }
    
    }
    

    Some notes:

    • There are no methods with many parameters.
    • The additional checking can be done in the MyClass constructor.
    • I made the constructor's visibility package-wide to avoid the "synthetic-access" warning.
    • Same for the builder's instance fields.
    • The only way to construct an instance of MyClass is via the Builder.
    0 讨论(0)
提交回复
热议问题