我有一个简单的问题,尝试使用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。
有什么好的建议如何做到这一点没有重复?
谢谢。 丹尼尔
答案 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");