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

时间:2022-06-24 23:20:42

This is more of a style question, where I'm unsure what solution to my problem would be the "cleanest".

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

The implementation details are not important, what I want to do is the following:

实现细节并不重要,我想做的是以下内容:

I've got an abstract class that is extended by several subclasses which are all very similar in nature. I want to hide these classes from the client by making them instantiable only through a static method in the superclass which returns a superclass reference to a subclass instance (the concrete class is determined by the method parameters). So far so good, I believe that's a very common thing to do.

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

Now, these subclasses I'm talking about can be divided into two groups, one group, whose members require two parameters in order to be constructed and another group, whose members need an additional parameter.

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

So now my question is this: How can I let the client obtain both of these types via a static method like the one mentioned above. Do I provide two static methods with different paramter lists? Do I force the client to pass a zero on the third optional parameter that the first group doesnt need? Is there a design pattern for this? (I have considered the Builder pattern from Effective Java, but as far as I understnad it that ones usually used in a different context). Or do I modify my inheritance hierarchy?

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

Any answers would be appreciated!

任何答案将不胜感激!

EDIT:

I believe my question is a little bit convoluted at the moment, all add a little bit of code to make it clearer:

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

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 个解决方案

#1


You have two options :

您有两种选择:

Option 1

Your static factory method in the super class can be implemented using var-args :

超类中的静态工厂方法可以使用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;
}

Option 2

Alternately, you could overload the newInstance method and have one that takes 2 parameters and the other that takes 3 parameters.

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

There are pros and cons of both approaches as described below :

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

  1. When the frequency at which you expect new fields to be introduced in existing subclasses or the frequency at which you expect new subclasses to be introduced with more fields than the existing ones is extremely low, approach 1 is a better option.
  2. 当您期望在现有子类中引入新字段的频率或者您希望引入新子类的频率比现有子字段更多的字段时,方法1是更好的选择。

  3. When the frequency at which you expect new fields to be introduced in existing subclasses or the frequency at which you expect new subclasses to be introduced with more fields than the existing ones is relatively higher, approach 2 is a better option since approach 1 will result in a very large method body.
  4. 当您希望在现有子类中引入新字段的频率或者您希望引入新子类的频率比现有子字段更多时,相对较高的方法2,方法2是更好的选择,因为方法1将导致一个非常大的方法体。

#2


You could pass a configuration strings, or configuration object (e.g. Properties) which has as much detail as the implementation needs. It could be 1 or 100 arguments. However, for the caller there is one and only wrapping argument passed.

您可以传递配置字符串或配置对象(例如,属性),其具有与实现需要一样多的细节。它可以是1或100个参数。但是,对于调用者,只有一个包装参数被传递。

#3


It depends. It sounds like that your superclass static method returns a SuperClass instance. If so, you can return different subclass instances according to the additional parameter.

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

Consider an abstract class Vehicle. Now two abstract classes SingleDeckVehicle and MultiDeckVehicle extend Vehicle and let the first two parameters be the number of wheels and the number of seats, and the additional parameter be the number of decks of the vehicle. Then, the number of deck will be important and indeed your client will pass a 1 as the third argument if he/she wants a SingleDeckVehicle instance.

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

However, you can also create another static method. Suppose you have defined a static method Vehicle.getVehicle(int wheelNo, int seatNo, int deckNo). You may also define another: Vehicle.getSingleDeckVehicle(int wheelNo, int seatNo) which returns Vehicle.getVehicle(wheelNo, seatNo, 1);.

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

A similar example is BorderFactory: http://docs.oracle.com/javase/7/docs/api/javax/swing/BorderFactory.html. I hope I understood your question correctly...

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

#1


You have two options :

您有两种选择:

Option 1

Your static factory method in the super class can be implemented using var-args :

超类中的静态工厂方法可以使用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;
}

Option 2

Alternately, you could overload the newInstance method and have one that takes 2 parameters and the other that takes 3 parameters.

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

There are pros and cons of both approaches as described below :

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

  1. When the frequency at which you expect new fields to be introduced in existing subclasses or the frequency at which you expect new subclasses to be introduced with more fields than the existing ones is extremely low, approach 1 is a better option.
  2. 当您期望在现有子类中引入新字段的频率或者您希望引入新子类的频率比现有子字段更多的字段时,方法1是更好的选择。

  3. When the frequency at which you expect new fields to be introduced in existing subclasses or the frequency at which you expect new subclasses to be introduced with more fields than the existing ones is relatively higher, approach 2 is a better option since approach 1 will result in a very large method body.
  4. 当您希望在现有子类中引入新字段的频率或者您希望引入新子类的频率比现有子字段更多时,相对较高的方法2,方法2是更好的选择,因为方法1将导致一个非常大的方法体。

#2


You could pass a configuration strings, or configuration object (e.g. Properties) which has as much detail as the implementation needs. It could be 1 or 100 arguments. However, for the caller there is one and only wrapping argument passed.

您可以传递配置字符串或配置对象(例如,属性),其具有与实现需要一样多的细节。它可以是1或100个参数。但是,对于调用者,只有一个包装参数被传递。

#3


It depends. It sounds like that your superclass static method returns a SuperClass instance. If so, you can return different subclass instances according to the additional parameter.

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

Consider an abstract class Vehicle. Now two abstract classes SingleDeckVehicle and MultiDeckVehicle extend Vehicle and let the first two parameters be the number of wheels and the number of seats, and the additional parameter be the number of decks of the vehicle. Then, the number of deck will be important and indeed your client will pass a 1 as the third argument if he/she wants a SingleDeckVehicle instance.

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

However, you can also create another static method. Suppose you have defined a static method Vehicle.getVehicle(int wheelNo, int seatNo, int deckNo). You may also define another: Vehicle.getSingleDeckVehicle(int wheelNo, int seatNo) which returns Vehicle.getVehicle(wheelNo, seatNo, 1);.

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

A similar example is BorderFactory: http://docs.oracle.com/javase/7/docs/api/javax/swing/BorderFactory.html. I hope I understood your question correctly...

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