帮助创建泛型类以避免代码重复

时间:2009-12-03 20:53:18

标签: java generics google-app-engine dry

我有一个简单的问题,尝试使用Appengine保持DRY。

除了作为参数发送的对象外,下面的两个函数是相同的。实际上我有15个这样的功能。我试图找到一种方法来创建超类或通用来实现这一点。

public void deleteRecord(Person s) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        Person p = pm.getObjectById(Person.class, s.getId());
        pm.deletePersistent(p);
    } finally {
        pm.close();
    }
}

public void deleteRecord(Product s) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        Product p = pm.getObjectById(Product.class, s.getId());
        pm.deletePersistent(p);
    } finally {
        pm.close();
    }
}

不幸的是,似乎我不能使用泛型,因为泛型不支持T.class。

有什么好的建议如何做到这一点没有重复?

谢谢。 丹尼尔

6 个答案:

答案 0 :(得分:4)

你不需要泛型;使用thing.getClass():

public void deleteRecord(Object thing) {
    ...
    Object o = pm.getObjectById(thing.getClass(), s.getId());
    ...
}

(如果传入的参数为null,则应在此处添加空值检查)

[注意:当我发现它之后我发现它时我改变了我的答案,当时我意识到你不需要仿制药......]

答案 1 :(得分:4)

这可能不是最简单的做事方式,但我不能不认为从长远来看这将是最有意义的。

创建界面

// This is a terrible name, I know
public interface Identifier {
    // Assumes ID was an int
    public int getId();
    // Maybe have setId, too
}

在每个类中,实现接口及其方法

public class Person implements Identifier {
    public int getId() {
        //Implementation details here
    }
}

最后,你的删除方法:

public void deleteRecord(Identifier s) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        Identifier p = pm.getObjectById(s.getClass(), s.getId());
        pm.deletePersistent(p);
    } finally {
        pm.close();
    }
}

注意:我还没有完全测试过这个...具体来说,我没有测试过pm.deletePersistent(p)是否适用于PersistenceManager

答案 2 :(得分:2)

最简单的方法是将类型作为参数引入:

public <T> void deleteRecord(Class<T> type, T s) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
                T p = pm.getObjectById(type, s.getId());
                pm.deletePersistent(p);
        } finally {
                pm.close();
        }
}

如果你的人员,产品等只是简单的类而且没有子类,你可以使用getClass()而不是像Scott建议的那样指定一个显式参数。

答案 3 :(得分:2)

DRY是一个很好的原则。 KISS也是如此; - )

public void deleteRecord(Class classOfProduct, Object id) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
            Object p = pm.getObjectById(classOfProduct, id);
            pm.deletePersistent(p);
    } finally {
            pm.close();
    }
}

这将被调用,例如:

theObject.deleteRecord(Person.class, s.getId());
theObject.deleteRecord(Product.class, s.getId());

由于这是一个void方法,并且PersistenceManager似乎不适用于泛型类型,我建议避免使用泛型。如果适用,此方法还有额外的好处,您无需修改​​产品,人员等的类型层次结构。

缺点是,如果从多个地方调用此方法,可能会有很多地方更改签名 - 但很容易让编译器找出需要多长时间。

答案 4 :(得分:1)

如果你在DAO中使用它,我倾向于用类初始化它。也许

public class DAO<T> {

  private Class klass

  public DAO(Class klass) {
    this.klass = klass;
  }

  public void deleteRecord(T record) {
    PersistenceManager pm = PMF.get().getPersistenceManager();     
    try {     
      T p = pm.getObjectById(this.klass, record.getId());     
      pm.deletePersistent(p);     
    } finally {     
      pm.close();     
    }
  }
}

答案 5 :(得分:0)

您可以使用枚举隐藏此内容:

class FetchableThing {}
class Person extends FetchableThing {}
class Organisation extends FetchableThing {}

enum DAO<T extends fetchableThing> {
    Person(Person.class), Organisation(Organisation.class);

    private Class<T> myClass;
    private DAO(Class<T> myClass) { this.myClass=myClass;}

    public delete(String id) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            T p = (T) pm.getObjectById(myClass, id);
            pm.deletePersistent(p);
        } finally {
            pm.close();
        }
    }
}

DAO.Person.delete("1234");
DAO.Organsation.delete("1234");