0

我一直在做一个项目,遇到了一个关于如何进行设计(面向对象)的令人费解的问题。我有不同类别的对象,例如 、、Employee等,它们具有相同的数据:名称、ID 号等。到目前为止,我已经制作了一个界面,以及这些不同类别中的每一个这个界面。当我尝试检索数据时出现问题。GroundskeeperCustomerPersonextends

如果我只想检索其中一个类别的对象,比如 a Customer,我必须创建一个新方法getCustomers(). 如果我想获得所有员工,我必须创建另一个类似的方法,称为getEmployees(). 这对每个类别继续进行。问题是这些方法的实现几乎相同,因为每个类别的数据都是相同的。唯一的区别是每个都只返回一个特定的类别。

有没有更好的方法来做到这一点,我只需要一种方法,而不是重复自己(本着 DRY 的精神)?

注意:这些类别必须是分开的,因为在路上,我需要将每个类别放在数据库中自己的表中,所以在某些时候必须分开类别。

可能的解决方案:

我找到了解决此问题的方法,您的建议对找到它有很大帮助(@Adam me)。我没有对每个类别进行单独的方法调用,而是使用了一个泛型方法,其中类别作为泛型参数提供给该方法。此外,类别的类作为数据库表的键提供。

例如,用于获取Person特定类别的签名将是:

public <T extends Person> Queue<T> getPersons (Class<T> key) {...}

并调用该方法,Customer比如说,调用将是:

Queue<Customer> customers = dataStore.<Customer>getPersons(Customer.class);

Class<T>只是使用了一个键,并且在方法内部getPersons(...),有一个Map将类映射到数据库中的表(Map<Class<? extends Person>, String>)。因此,当Person提供 的类时(CustomerEmployee等),在地图上执行查找,然后从与该类关联的数据库表中检索数据。

虽然它与建议的答案不同,但我非常感谢您的回复:他们引导我朝着正确的方向寻求解决方案。

4

4 回答 4

0

您可以使用将要返回的类名作为参数的方法。任何继承 Person 的类仍然是 Person 对象,因此您仍然可以这样引用它们。

public Person (String typeOfPerson) {
  return all persons where:      
    person.getClass().getName().equals(typeOfPerson);
}
于 2013-05-20T21:26:46.663 回答
0

您可以通过实现基于过滤器的结构来获取所需的对象。

interface Person { }

class Employee implements Person { }
class Costumer implements Person { }

interface Criteria {
    public boolean match(Person p);
}

class ClassNameCriteria implements Criteria {
    private String className;

    public TypeCriteria(String className) {
        this.className = className;
    }

    public function match(Person p) {
        return person.getClass().getName().equalsIgnoreCase(this.className);
    }
}

class Client {
    private Collection<Person> persons;
    public Collection<Person> getByCriteria(Criteria c) {
        Collection<Person> col = new ArrayList<Person>();
        for(Person p : persons) {
           if (c.match(p)) { 
               col.add(p);
           }
        }
        return col
    }
}

Client client = new Client();
// Adds some persons...
Criteria c = new ClassNameCriteria("Employee");
Collection<Person> = client.getByCriteria(c); // If you need, you can safely cast to Collection<Employee>
于 2013-05-20T22:51:50.867 回答
0

可能的解决方案:

我找到了解决此问题的方法,您的建议对找到它有很大帮助(@Adam me)。我没有对每个类别进行单独的方法调用,而是使用了一个泛型方法,其中类别作为泛型参数提供给该方法。此外,类别的类作为数据库表的键提供。

例如,用于获取Person特定类别的签名将是:

public <T extends Person> Queue<T> getPersons (Class<T> key) {...}

并调用该方法,Customer比如说,调用将是:

Queue<Customer> customers = dataStore.<Customer>getPersons(Customer.class);

Class<T>只是使用了一个键,并且在方法内部getPersons(...),有一个Map将类映射到数据库中的表(Map<Class<? extends Person>, String>)。因此,当Person提供 的类时(CustomerEmployee等),在地图上执行查找,然后从与该类关联的数据库表中检索数据。

虽然它与建议的答案不同,但我非常感谢您的回复:他们引导我朝着正确的方向寻求解决方案。

于 2013-05-22T13:51:21.043 回答
0

您可以使用 Bloch 的 Effective java book 中的设计(忘记了哪个项目)。它利用了两个世界,并从两者中汲取了最好的:

  • IPerson:是你想要的getter和setter的接口
  • AbstractPerson 实现 IPerson:被称为Skeleton类,并具有字段和访问器,或者您想要共享的任何代码。
  • 子类(例如您的客户)扩展 AbstractPerson:对您的 Person 的任何特定添加。

这个解决方案的美妙之处在于您在 Skeleton 类中有一些共享代码,但独立于它。一些已经扩展了其他类的新类可以实现该接口,因此也可以成为 IPerson。

于 2013-05-28T15:59:30.183 回答