简体   繁体   中英

Java reduce number of constructors

Suppose I have some class that has constructors, each of which has 2 params for example I have 5 types, two of them can be passed as first param and three as second

Suppose the types are A,B,C,D,E. Basically I have something like this:

public SomeClass(A,C) {}
public SomeClass(A,D) {}
public SomeClass(A,E) {}

public SomeClass(B,C) {}
public SomeClass(B,D) {}
public SomeClass(B,E) {}

So as you can see there are all possible combinations of these types and there aren't optional params, like in standard builder pattern.

What can I do to reduce number of constructors? Is there some pattern to help me?

EDIT

I can't use standard builder because if I supplied A then I can't supply B and if I supplied C then I can't supply D or E

You can create a restricted builder pattern:

class MyBuilder {

    public MyBuilder(A) { ... }
    public MyBuilder(B) { ... }

    public SomeClass build(C) { ... }
    public SomeClass build(D) { ... }
    public SomeClass build(E) { ... }

}

Example usage:

new MyBuilder(A).build(C)

If you have only 6 possible combinations, I would probably tolerate the complexity and duplication in the existing code. But if there are more possibilities and/or the code will be extended in the future, then I would recommend this pattern here.


You can extend this pattern to more arguments, but it gets uglier because you need more intermediate classes. For 3 arguments, you might implement something like:

class MyBuilder1 {
    public MyBuilder1(A) { ... }
    public MyBuilder1(B) { ... }

    public MyBuilder2 build(C) { ... }
    public MyBuilder2 build(D) { ... }
    public MyBuilder2 build(E) { ... }

    class MyBuilder2 {
        public MyBuilder2(C) { ... }
        public MyBuilder2(D) { ... }
        public MyBuilder2(E) { ... }

        public SomeClass build(F) { ... }
        public SomeClass build(G) { ... }
    }
}

SomeClass x = new MyBuilder1(B).build(D).build(F);

Unfortunately the intermediate stage needs duplication of methods and constructors for types C, D, E.

Create 2 interfaces, one for your first parameter, one for your second parameter. A and B implement the first one, C,D and E the second one.

A suggestion. Put the logic into your builder equivalent class. Add a method to check that the parameter combination is valid.

class MyBuilder {

  int paramA;
  bool paramAset = false;

  long paramB
  bool paramBset = false;

  // etc for all parameters.

  void setParamA(int newAval) {
    if (checkParamA(newAval)) {
      paramA = newVal;
      paramAset = true;
    }
  }

  void setParamB(long newBval) {
    if (checkParamB(newBval)) {
      paramB = newBval;
      paramBset = true;
    }
  }

  // etc. for all parameters.

  // Parameter checker method.
  bool checkValid() {
    if (
        paramAset && !paramBset && /* other params */ ||
        !paramAset && paramBset && /* other params */ ||
        // other allowed parameter combinations
       ) {
      return true;
    } else {
      return false;
    }
  }

} // end class MyBuilder

Each parameter has its own value and a boolean to indicate whether it is set. The checker method only allows valid combinations of the booleans. Note that each parameter is specified as either set or not set in the checker to catch all invalid combinations. Your constructor for the main class needs to call the checker method and fail appropriately if the combination is invalid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM