获取方法:一对多

时间:2008-09-17 07:45:37

标签: java oop java-ee

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进行调用。

22 个答案:

答案 0 :(得分:9)

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

getEmployeeName(int BatchID)
getEmployeeName(对象SSN)(坏主意)
getEmployeeName(String Email)

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

答案 1 :(得分: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)));

您获得的内容类似于Hibernate中的Criteria API。

答案 2 :(得分:3)

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

除非你拥有相同数据类型的属性,否则我会进行重载。在这种情况下,我会做一些类似于你的第二个选项,但不是使用整数,我会使用Enum来保证类型的安全性和清晰度。而不是byte [],我使用Object(因为自动装箱,这也适用于基元)。

答案 3 :(得分:3)

我会选择“很多”方法。对我来说似乎更直观,更不容易出错。

答案 4 :(得分:2)

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

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

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

答案 5 :(得分:1)

@Stephan:很难超载这样的情况(一般情况下),因为参数类型可能没有区别性,例如,

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

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

答案 6 :(得分:1)

我将使用显式方法名称。维护该代码的每个人以及稍后我将理解该方法正在做什么而不必编写xml注释。

答案 7 :(得分:1)

第一个选择,毫无疑问。要明确。它将极大地帮助维护,并且确实没有任何缺点。

答案 8 :(得分:1)

有时使用specification pattern会更加方便。

例如:GetEmployee(ISpecification&lt; Employee&gt;规范)

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

NameSpecification:ISpecification&lt; Employee&gt;
{
 私人字符串名称;
 public NameSpecification(string name){this.name = name; }
 public bool IsSatisFiedBy(Employee employee){return employee.Name == this.name; }
}

NameSpecification spec = new NameSpecification(“Tim”);
员工tim = MyService.GetEmployee(spec);

答案 9 :(得分:0)

我会选择Query Objects。它们适用于直接访问表。如果你只局限于存储过程,它们会失去一些力量,但你仍然可以使它工作。

答案 10 :(得分:0)

这些方法中的逻辑大致相同吗?

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

如果类型之间的逻辑/程序差异很大,则可能优先考虑每种类型的方法。

答案 11 :(得分:0)

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

答案 12 :(得分:0)

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

重载似乎是最初的最佳方式,但是如果你最终无法在将来添加方法并且通过命名来搞乱它将会很麻烦。

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

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

答案 13 :(得分:0)

我同意斯蒂芬:一个任务,一个方法名称,即使你可以采取多种方式。 完全为您的情况提供了方法重载功能。

  • getEmployeeName(int BatchID)
  • getEmployeeName(String Email)

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

答案 14 :(得分:0)

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

答案 15 :(得分:0)

我个人更喜欢明确命名“... ByRoomNumber”,因为如果最终导致许多“重载”,最终会引入不需要的错误。明确是最好的方式。

答案 16 :(得分:0)

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

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

答案 17 :(得分:0)

如果您重写问题,最终可能会问:

“SELECT name FROM ...”
“从中选择SSN ......”
“选择电子邮件来自...”

“SELECT * FROM ...”

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

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

答案 18 :(得分:0)

在这样一个微不足道的案例中,我会超载。那就是:

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

etc.

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

我不知道为什么我会使用这个

getEmployeeName(int typeOfIdentifier, byte[] identifier)

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

答案 19 :(得分:0)

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

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

答案 20 :(得分:-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
}

答案 21 :(得分:-2)

您正在考虑使用C / C ++。

使用对象而不是标识符byte(或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
}

我认为最好使用未经检查的例外来表示不正确的输入。

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