10

getEmployeeNameByBatchId(int batchID)
getEmployeeNameBySSN(Object SSN)
getEmployeeNameByEmailId(String emailID)
getEmployeeNameBySalaryAccount(SalaryAccount SalaryAccount)

或者

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

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

这些方法将在一个 Servlet 中,并从一个提供给客户的 API 进行调用。

4

22 回答 22

9

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

getEmployeeName(int BatchID)
getEmployeeName(object SSN)(坏主意)
getEmployeeName(String Email)
等。

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

于 2008-09-17T07:49:00.120 回答
7

你可以使用类似的东西:

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)));

你得到的类似于CriteriaHibernate 中的 API。

于 2008-09-17T08:10:02.767 回答
3

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

于 2008-09-17T07:48:55.737 回答
3

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

我会选择重载,除非你有相同数据类型的属性。在这种情况下,我会做类似于你的第二个选项的事情,但我不会使用整数,而是使用 Enum 来确保类型安全和清晰。而不是 byte[],我会使用 Object(因为自动装箱,这也适用于原语)。

于 2008-09-17T08:08:39.650 回答
2

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

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

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

于 2008-09-17T07:59:57.970 回答
1

第一个选项,毫无疑问。明确。它将极大地有助于可维护性,并且确实没有缺点。

于 2008-09-17T07:50:26.357 回答
1

@Stephan:很难重载这样的情况(通常),因为参数类型可能没有区别,例如,

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

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

于 2008-09-17T07:55:49.870 回答
1

有时使用规范模式会更方便。

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

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

NameSpecification : ISpecification<Employee>
{
私有字符串名称;
public NameSpecification(string name) { this.name = name; }
public bool IsSatisFiedBy(Employee employee) { return employee.Name == this.name; }
}

NameSpecification 规范 = 新 NameSpecification("Tim");
员工 tim = MyService.GetEmployee(spec);

于 2008-09-17T08:15:49.383 回答
1

我将使用明确的方法名称。维护该代码的每个人和我以后都会明白该方法在做什么,而无需编写 xml 注释。

于 2008-09-17T08:46:52.353 回答
0

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

于 2008-09-17T07:49:07.873 回答
0

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

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

于 2008-09-17T07:52:58.237 回答
0

这些方法中的每一个内部的逻辑是否大致相同?

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

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

于 2008-09-17T07:54:18.780 回答
0

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

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

于 2008-09-17T07:55:50.197 回答
0

在像这样的微不足道的情况下,我会选择重载。那是:

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

etc.

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

我不明白为什么我会使用它

getEmployeeName(int typeOfIdentifier, byte[] identifier)

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

于 2008-09-17T07:58:07.273 回答
0

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

"SELECT name FROM ..."
"SELECT SSN FROM ..."
"SELECT email FROM ..."
vs.
"SELECT * FROM ..."

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

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

于 2008-09-17T07:58:59.253 回答
0

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

于 2008-09-17T08:09:16.607 回答
0

我同意 Stephan:一项任务,一种方法名称,即使您可以通过多种方式完成。方法重载功能完全适合您的情况。

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

并且不惜一切代价避免您的第二种解决方案。它闻起来像“你的老空* C”。同样,传递一个Java“对象”几乎和一个C“void *”一样糟糕。

于 2008-09-17T08:20:45.223 回答
0

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

重载最初似乎是最好的方法,但如果你最终无法在未来添加方法并且将事情弄乱命名,那将是一件麻烦事。

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

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

于 2008-09-17T08:26:56.470 回答
0

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

于 2008-09-17T13:16:59.707 回答
0

我会选择Query Objects。它们适用于直接访问表。如果您仅限于存储过程,它们会失去一些功能,但您仍然可以使其工作。

于 2008-09-18T00:15:20.810 回答
-1

将所有选项都放在一个枚举中,类似于以下内容

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
}
于 2008-09-17T10:12:48.293 回答
-2

您正在考虑 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
}

我认为最好使用未经检查的异常来表示输入错误。

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

于 2008-09-17T07:57:07.870 回答