具有相同数据的对象类别的模式?

时间:2013-05-20 21:18:07

标签: java database oop design-patterns

我一直致力于一个项目,并遇到了一个关于如何处理设计(面向对象)的令人费解的问题。我有不同类别的对象,例如EmployeeGroundskeeperCustomer等具有相同数据的对象:名称,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的类(CustomerEmployee等)时,将在地图上执行查找,然后从关联的数据库表中检索数据那个班。

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

4 个答案:

答案 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的类(CustomerEmployee等)时,将在地图上执行查找,然后从关联的数据库表中检索数据那个班。

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

答案 3 :(得分:0)

您可以使用Bloch的Effective java书籍中的设计(忘记了哪个项目)。它利用了两个世界并从两者中获得了最好的效果:

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

此解决方案的美丽是您在Skeleton类中有一些共享代码,但独立。一些已经扩展了其他类的新类可以实现接口,从而也成为IPerson。