【问题标题】:Design a Java interface: a method with variable numbers of parameters设计一个Java接口:一个参数数量可变的方法
【发布时间】:2016-05-12 15:45:59
【问题描述】:

我刚刚在设计一个接口时遇到了一个问题,该接口的方法可能具有可变数量的输入参数。

public interface FoobarSerialization<T> {
    Foobar serialize(T obj); 
}

问题是,对于实现此接口的类,它们需要不同数量的输入参数。

public class FoobarA implements FoobarSerialization<FoobarA> {
    @Override
    public Foobar serialize(FoobarA obj, int bar) {
        //...
    }
}


public class FoobarB implements FoobarSerialization<FoobarB> {
    @Override
    public Foobar serialize(FoobarB obj, Date date, String str) {
        //...
    }
}

有没有好的设计或任何真正的方法来解决这个问题?我知道接口中的方法可以声明为:

Foobar serialize(T... obj); 

但我不确定设计这样的界面是否是一个好习惯。

有什么想法吗?

更新:我使用接口的意图来自需要为不同目的进行序列化和反序列化的类的集合。它们作为同一域下的组件。但是它们的序列化方法是完全不同的,特别是考虑到它们对不共享任何共同特征或类的对象和服务的依赖。

我想这里要问的正确问题是:就设计而言,当退出一组具有相同行为(序列化、反序列化、doSomething 等)但输入参数不同的类时,最好的方法是什么?

【问题讨论】:

  • 这不是你应该有接口的东西。拥有一个接口的意义在于,如果你有一个接口的实例,你应该总是能够用相同的参数调用它,而这里不是这样。
  • @LouisWasserman 同意。在这种情况下使用接口似乎不是一个好主意。那么这里最好用什么?
  • 最好的东西就是什么都没有。直接写方法即可;不要尝试任何花哨的继承魔法。

标签: java parameters interface


【解决方案1】:

组合模式来拯救。

在您的特定情况下,我将创建只接受 1 个参数的接口:

public interface Serializer<T> {

    Foobar serialize(T object);

}

现在,如果您需要序列化多个字段,您只需创建一个对象,其中包含您需要序列化的所有字段:

class FoobarBundle {

    String stringField;
    int intField;
    byte[] arrayField;

    /* ... */

}

并编写一堆序列化程序:FoobarBundleSerializerStringSerializerIntegerSerializerByteArraySerializer。最后像这样组合FoobarBundleSerializer中的所有序列化器:

class FoobarBundleSerializer implements Serializer<FoobarBundle> {

    StringSerializer stringSerializer;
    IntegerSerializer integerSerializer;
    ByteArraySerializer byteArraySerializer;

    /* constructor here */

    @Override
    public Foobar serialize(FoobarBundle bundle) {
        Foobar foobarString = stringSerializer.serialize(bundle.stringField);

        Foobar foobarInteger = integerSerializer.serialize(bundle.intField);

        Foobar foobarByteArray = byteArraySerializer.serialize(bundle.byteArrayField);

        return combineFoobarSomehow(foobarString, foobarInteger, foobarByteArray);
    }

}

【讨论】:

    【解决方案2】:

    您的使用范围可能会有所不同,但通常应避免混淆使用(例如,相同数量但不同类型的参数)具有相同名称的方法。尽管可以借助方法重载,但它被认为不太理想。如果参数列表是可管理的,您应该以不同的方式命名该方法以避免歧义。见Item 26 in Effective Java 2

    可变参数方法没问题,但在 Java 中,最佳做法是指定至少一个具体参数,后跟可变数量的相同类型的参数。这可能不适用于您的情况,因为像public Foobar serialize(FoobarB obj, Date date, String str); 这样的方法没有可变参数语法。使用(Object ... objects) 之类的语法可能是可以接受的,但这种做法被认为普遍适用。

    将此与printf 之类的方法进行对比,该方法可以并且应该能够将可变数量的任何类型(包括原语)参数输出到输出流。

    【讨论】:

      猜你喜欢
      • 2011-11-28
      • 2022-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多