Managing constructors with many parameters in Java

In some of our projects, there's an class hierarchy that adds more parameters as it goes down the chain. At the bottom, some of the classes can have up to 30 parameters, 28 of which are just being passed into the super constructor.

I'll acknowledge that using automated DI through something like Guice would be nice, but because of some technical reasons, these specific projects are constrained to Java.

A convention of organizing the arguments alphabetically by type doesn't work because if a type is refactored (the Circle you were passing in for argument 2 is now a Shape) it can suddenly be out of order.

This question might be to specific and fraught with "If that's your problem, you're doing it wrong at a design level" criticisms, but I'm just looking for any viewpoints.


The Builder Design Pattern might help. Consider the following example

public class StudentBuilder
{
    private String _name;
    private int _age = 14;      // this has a default
    private String _motto = ""; // most students don't have one

    public StudentBuilder() { }

    public Student buildStudent()
    {
        return new Student(_name, _age, _motto);
    }

    public StudentBuilder name(String _name)
    {
        this._name = _name;
        return this;
    }

    public StudentBuilder age(int _age)
    {
        this._age = _age;
        return this;
    }

    public StudentBuilder motto(String _motto)
    {
        this._motto = _motto;
        return this;
    }
}

This lets us write code like

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

If we leave off a required field (presumably name is required) then we can have the Student constructor throw an exception. And it lets us have default/optional arguments without needing to keep track of any kind of argument order, since any order of those calls will work equally well.


Can you encapsulate related parameters inside an object?

eg, if parameters are like


MyClass(String house, String street, String town, String postcode, String country, int foo, double bar) {
  super(String house, String street, String town, String postcode, String country);
  this.foo = foo;
  this.bar = bar;

then you could instead have:


MyClass(Address homeAddress, int foo, double bar) {
  super(homeAddress);
  this.foo = foo;
  this.bar = bar;
}


What you probably want to do is have a Builder class. Then you would do something like this:

MyObject obj = new MyObjectBuilder().setXxx(myXxx)
                                    .setYyy(myYyy)
                                    .setZzz(myZzz)
                                    // ... etc.
                                    .build();

See page 8 and following of this Josh Bloch presentation (PDF), or this review of Effective Java

链接地址: http://www.djcxy.com/p/3544.html

上一篇: Java可选参数

下一篇: 用Java中的许多参数管理构造函数