我一直致力于一个项目,并遇到了一个关于如何处理设计(面向对象)的令人费解的问题。我有不同类别的对象,例如Employee
,Groundskeeper
,Customer
等具有相同数据的对象:名称,ID号等。到目前为止,我已经制作了单个界面Person
,以及这些不同类别中的每一个extends
此界面。当我尝试检索数据时出现问题。
如果我只想检索其中一个类别的对象,比如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
的类(Customer
,Employee
等)时,将在地图上执行查找,然后从关联的数据库表中检索数据那个班。
虽然它与建议的答案不同,但我非常感谢您的回答:他们引导我朝着正确的方向寻求解决方案。
答案 0 :(得分:0)
您可以使用一种方法,该方法将您希望作为参数返回的类名称。任何继承Person的类仍然是Person对象,因此您仍然可以像这样引用它们。
public Person (String typeOfPerson) {
return all persons where:
person.getClass().getName().equals(typeOfPerson);
}
答案 1 :(得分: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>
答案 2 :(得分: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
的类(Customer
,Employee
等)时,将在地图上执行查找,然后从关联的数据库表中检索数据那个班。
虽然它与建议的答案不同,但我非常感谢您的回答:他们引导我朝着正确的方向寻求解决方案。
答案 3 :(得分:0)
您可以使用Bloch的Effective java书籍中的设计(忘记了哪个项目)。它利用了两个世界并从两者中获得了最好的效果:
此解决方案的美丽是您在Skeleton类中有一些共享代码,但独立。一些已经扩展了其他类的新类可以实现接口,从而也成为IPerson。