具有可变数量的构造函数参数的子类的静态工厂方法

时间:2015-05-03 07:24:51

标签: java inheritance subclass

这更像是一个风格问题,我不确定我的问题的解决方案是什么“最干净”。

实施细节并不重要,我想做的是:

我有一个抽象类,它由几个子类扩展,这些子类本质上非常相似。我想从客户端隐藏这些类,只能通过超类中的静态方法使它们可实例化,该方法返回对子类实例的超类引用(具体类由方法参数确定)。 到目前为止,我认为这是一件很常见的事情。

现在,我正在谈论的这些子类可以分为两组,一组,其成员需要两个参数才能构建,另一组,其成员需要一个额外的参数。

所以现在我的问题是:如何让客户端通过上面提到的静态方法获得这两种类型。我是否提供了两种带有不同参数列表的静态方法?我是否强制客户端在第一组不需要的第三个可选参数上传递零值?这有设计模式吗? (我已经考虑过Effective Java中的Builder模式,但据我所知,通常在不同的上下文中使用它)。或者我是否修改了继承层次结构?

任何答案都将不胜感激!

编辑:

我认为我的问题目前有点复杂,所有都添加了一些代码以使其更清晰:

abstract class SuperClass{

    public static SuperClass getSuperClass(String type, int i1, int i2, int optional) {

        /*
         *'type' alone determines which concrete subclass is instanciated
         *'optional' is only needed for the construction for some of those 'types'
         *so the implementation of this method might look like this:
         */

        switch(type) {
            case "1":
                return new Subclass1(i1, i2);
                break;
            case "2":
                return new Subclass2(i1, i2, optional);
                break;

        /*
         *So the problem is this: always passing 'optional' is weird if it 
         *is then simply discarded in some cases.
         *Overloading is weird as well because I don't want to split up 
         *the switch statement or check for exceptions in every case 
         *(when optional is/is not declared for types where it 
         *shouldn't/should be)
         */
    }

}

3 个答案:

答案 0 :(得分:1)

您有两种选择:

选项1

超类中的static factory method可以使用var-args实现:

public static SuperClass newInstace(int...parameters) {
     SuperClass superClass = null;
     if(parameters.length == 2) {
          if(parameters[1]>=5) {//instantiate a subclass based on a value
             super = new SubClass1(parameters[0],parameters[1]);
          } else {
             super = new SubClass2(parameters[0],parameters[1]);
          }

     } else if(parameters.length == 3) {
           if(parameters[2]>=5) {
             super = new SubClass3(parameters[0],parameters[1],parameters[2]);
          } else {
             super = new SubClass4(parameters[0],parameters[1],parameters[2]);
          }
     } else {
          throw new IllegalArgumentException("Invalid number of parameters passed to newInstance. Expected number of parameters [min = 2, max = 3]")
     }

     return superClass;
}

选项2

或者,您可以重载newInstance方法,并使用一个接受2个参数,另一个接受3个参数。

两种方法的优点和缺点如下所述:

  1. 当您希望在现有子类中引入新字段的频率或您希望引入新子类的频率比现有子字段更多的字段时,方法1是更好的选择。
  2. 当您希望在现有子类中引入新字段的频率或者您希望引入新子类的频率比现有子字段更多的字段时,相比更高的方法2,方法2是更好的选择将导致一个非常大的方法体。

答案 1 :(得分:0)

您可以传递配置字符串或配置对象(例如,属性),其中包含与实现需求一样多的详细信息。它可以是1或100个参数。但是,对于调用者来说,只传递了一个包装参数。

答案 2 :(得分:0)

这取决于。听起来你的超类静态方法返回一个SuperClass实例。如果是这样,您可以根据附加参数返回不同的子类实例。

考虑一个抽象类Vehicle。现在两个抽象类SingleDeckVehicleMultiDeckVehicle扩展Vehicle,让前两个参数为车轮数和座位数,附加参数为车辆甲板数。然后,甲板的数量将是重要的,如果他/她想要1实例,您的客户确实会传递SingleDeckVehicle作为第三个参数。

但是,您也可以创建另一个静态方法。假设您已定义静态方法Vehicle.getVehicle(int wheelNo, int seatNo, int deckNo)。您还可以定义另一个:Vehicle.getSingleDeckVehicle(int wheelNo, int seatNo),返回Vehicle.getVehicle(wheelNo, seatNo, 1);

一个类似的例子是BorderFactory: http://docs.oracle.com/javase/7/docs/api/javax/swing/BorderFactory.html。我希望我能正确理解你的问题......