getEmployeeNameByBatchId(int batchID)
getEmployeeNameBySSN(对象 SSN)
getEmployeeNameByEmailId(String emailID)
getEmployeeNameBySalaryAccount(SalaryAccount 工资帐户)

或者

getEmployeeName(int typeOfIdentifier, byte[]identifier) -> 在此方法中,typeOfIdentifier 告诉标识符是否为batchID/SSN/emailID/salaryAccount

上述哪一种是实现 get 方法的更好方法?

这些方法将位于 Servlet 中,并且将从提供给客户的 API 进行调用。

有帮助吗?

解决方案

为什么不重载 getEmployeeName(??) 方法?

getEmployeeName(int BatchID)
getEmployeeName(对象 SSN)(馊主意)
getEmployeeName(字符串电子邮件)
ETC。

对我来说似乎是一个很好的“多”方法。

其他提示

你可以使用类似的东西:

interface Employee{
    public String getName();
    int getBatchId();
}
interface Filter{
    boolean matches(Employee e);
}
public Filter byName(final String name){
    return new Filter(){
        public boolean matches(Employee e) {
            return e.getName().equals(name);
        }
    };
}
public Filter byBatchId(final int id){
    return new Filter(){
        public boolean matches(Employee e) {
            return e.getBatchId() == id;
        }
    };
}
public Employee findEmployee(Filter sel){
    List<Employee> allEmployees = null;
    for (Employee e:allEmployees)
        if (sel.matches(e))
            return e;
    return null;
}
public void usage(){
    findEmployee(byName("Gustav"));
    findEmployee(byBatchId(5));
}

如果您通过 SQL 查询进行过滤,您将使用 Filter 用于组成 WHERE 子句的接口。

这种方法的好处是您可以轻松地将两个过滤器组合起来:

public Filter and(final Filter f1,final Filter f2){
    return new Filter(){
        public boolean matches(Employee e) {
            return f1.matches(e) && f2.matches(e);
        }
    };
}

并像这样使用它:

findEmployee(and(byName("Gustav"),byBatchId(5)));

你得到的类似于 Criteria Hibernate 中的 API。

我会采用“多”方法。对我来说这似乎更直观并且不太容易出错。

我不喜欢 getXByY() - 这在 PHP 中可能很酷,但我只是不喜欢 Java 中的它 (ymmv)。

我会选择重载,除非您具有相同数据类型的属性。在这种情况下,我会执行与您的第二个选项类似的操作,但我不会使用整数,而是使用枚举来确保类型安全性和清晰度。我将使用 Object(由于自动装箱,这也适用于基元)而不是 byte[]。

这些方法是使用重载的完美示例。

getEmployeeName(int batchID)
getEmployeeName(Object SSN)
getEmployeeName(String emailID)
getEmployeeName(SalaryAccount salaryAccount)

如果方法内部有共同的处理,就再写一个 getEmplyeeNameImpl(...) 并将共同的代码提取到那里,避免重复

第一个选择,毫无疑问。明确一点。它将极大地提高可维护性,并且实际上没有任何缺点。

@斯蒂芬:(一般来说)很难重载这样的情况,因为参数类型可能没有区别,例如,

  • getEmployeeNameByBatchId(int batchId)
  • getEmployeeNameByRoomNumber(int roomNumber)

另请参阅原始帖子中的两个方法 getEmployeeNameBySSN、getEmployeeNameByEmailId。

我将使用明确的方法名称。每个维护该代码的人和我稍后都会了解该方法的作用,而无需编写 xml 注释。

有时使用 规格图案.

例如:GetEmployee(ISpecification<Employee> 规范)

然后开始定义您的规格...

名称规格:I规范<员工>
{
私有字符串名称;
公共 NameSpecification(字符串名称) { this.name = name;}
公共 bool IsSatisFiedBy(Employee 员工) { return 员工.Name == this.name;}
}

NameSpecification 规范 = new NameSpecification("Tim");
员工蒂姆 = MyService.GetEmployee(spec);

我会使用第一个选项,或者在这种情况下重载它,因为您有 4 个不同的参数签名。然而,具体有助于 3 个月后理解代码。

这些方法内部的逻辑大体相同吗?

如果是这样,带有标识符参数的单一方法可能更有意义(简单并减少重复代码)。

如果类型之间的逻辑/过程差异很大,则可能会首选每种类型的方法。

正如其他人所建议的,第一个选择似乎是好的选择。当您编写代码时,第二个可能有意义,但是当其他人稍后出现时,就很难弄清楚如何使用代码。(我知道,你有评论,你总是可以深入研究代码,但 GettemployeeNameById 更不言自明)

笔记:顺便说一句,在某些情况下可能需要考虑使用枚举。

在这样的小情况下,我会选择重载。那是:

getEmployeeName( int batchID );
getEmployeeName( Object SSN );

etc.

只有在特殊情况下,我才会在方法名称中指定参数类型,即如果参数的类型难以确定,如果有多种类型的参数具有相同的数据类型(batchId 和 employeeId,均为 int),或者每个参数类型的检索员工的方法完全不同。

我不明白为什么我会用这个

getEmployeeName(int typeOfIdentifier, byte[] identifier)

因为它要求被调用者和调用者都根据 typeOfIdentifier 来转换值。糟糕的设计。

如果你重写这个问题,你最终可能会问:

“从...中选择名称”
“从...选择 SSN”
“从...选择电子邮件”

“从...中选择*”

我想这个问题的答案很简单,每个人都知道。

如果更改 Employee 类会发生什么?例如。:您必须删除电子邮件并添加新的过滤器(例如部门)。对于第二种解决方案,如果您只是更改 int 标识符“常量”的顺序,那么您将面临巨大的风险,无法注意到任何错误。使用第一个解决方案,您总是会注意到,如果您在一些长期被遗忘的类中使用该方法,否则您会忘记修改新标识符。

我个人更喜欢显式命名“...ByRoomNumber”,因为如果最终出现许多“过载”,您最终会引入不需要的错误。恕我直言,明确是最好的方法。

我同意斯蒂芬的观点:一项任务,一种方法名称, ,即使你可以通过多种方式做到这一点。方法重载功能正是针对您的情况提供的。

  • getEmployeeName(int BatchID)
  • getEmployeeName(字符串电子邮件)
  • ETC。

避免 不惜一切代价提供您的第二个解决方案。它闻起来像“thy olde void * of C”。同样,传递 Java“对象”几乎与传递 C“void *”一样糟糕。

如果您有一个好的设计,您应该能够确定是否可以使用重载方法,或者您是否会遇到一个问题:如果重载,您最终会得到两个具有相同参数类型的方法。

最初,重载似乎是最好的方法,但是如果您最终无法在将来添加方法并且命名会搞砸,那么这将是一个麻烦。

就我个人而言,我支持每个方法都有唯一名称的方法,这样您以后在尝试重载相同参数的对象方法时就不会遇到问题。另外,如果有人将来扩展你的类并实现另一个 void getEmployeeName(String name) ,它不会覆盖你的类。

总而言之,为每个方法使用唯一的方法名称,从长远来看,重载只会导致问题。

jrudolf 在他的示例中提出的搜索过程和搜索标准之间的解耦非常好。我想知道为什么它不是投票最多的解决方案。我错过了什么吗?

我会和 查询对象. 。它们非常适合直接访问表。如果您仅限于存储过程,它们会失去一些功能,但您仍然可以使其工作。

第一个可能是 Java 中最好的,因为它是类型安全的(与另一个不同)。此外,对于“普通”类型,第二种解决方案似乎只为用户提供麻烦的使用。但是,由于您使用 Object 作为 SSN 的类型(它具有超出 Object 的语义),因此您可能无法使用该类型的 API。

总而言之,在这种特殊情况下,我会对该方法与许多吸气剂一起使用。如果所有标识符都有自己的类类型,我可能会选择第二条路线,但在类上进行内部切换,而不是提供/应用程序定义的类型标识符。

将所有选项放在一个枚举中,如下所示

GetEmployeeName(Enum identifier)
{
    switch (identifier)
    case eBatchID:
    {
        // Do stuff
    }
    case eSSN:
    {
    }
    case eEmailId:
    {
    }
    case eSalary:
    {
    }
    default:
    {
        // No match
        return 0;
    }
}

enum Identifier
{
    eBatchID,
    eSSN,
    eEmailID,
    eSalary
}

你正在考虑 C/C++。

使用对象而不是标识符字节(或 int)。

我的坏处是,重载方法更好,但使用 SSN 作为主键不太好

public ??? getEmployeeName(Object obj){

if (obj instanceof Integer){

  ...

} else if (obj instanceof String){

...

} else if .... // and so on


} else throw SomeMeaningFullRuntimeException()

return employeeName
}

我认为最好使用未经检查的异常来发出错误输入信号。

记录下来,以便客户知道期望的对象是什么。或者创建您自己的包装器。我更喜欢第一个选择。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top