当前位置: 动力学知识库 > 问答 > 编程问答 >

java - Help to create a generic class to avoid code duplication

问题描述:

I have a simple problem try to stay DRY using Appengine.

The 2 functions below are identical except for the object sent as parameter. In reality I have 15 functions like this. I am try to find a way to create a super class or a generic to achieve this.

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();

}

}

and

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();

}

}

Unfortunately it seems that I cannot use generics since generics don't support T.class.

Any good suggestion how to do this w/o duplicating?

Thank you.

Daniel

网友答案:

DRY is a good principle. So is 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();
    }
}

This would be called with, for example:

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

Since this is a void method, and PersistenceManager does not appear to work with generic types, I would advise avoiding using generics. This method, if applicable, has the added bonus that you won't need to modify the type hierarchy of Product, Person, etc.

The downside is that if this method is called from several places, there may be many places to change the signature - but it's easy to let the compiler find out how long it would take.

网友答案:

You don't need generics for this; use thing.getClass():

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

(you should add a null-check in there just in case the parameter passed in was null)

[Note: I changed my answer just after I posted it when I realized you don't need generics here...]

网友答案:

This may not be the easiest way to do things, but I can't help but think it would make the most sense in the long run.

Create an interface

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

And in each of your classes, implement the interface and its method

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

and finally, your delete method:

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();
    }
}

Note: I haven't completely tested this... Specifically, I haven't tested whether pm.deletePersistent(p) works with PersistenceManager.

网友答案:

The easiest way would be to introduce the type as a parameter:

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();
        }
}

If your Persons, Products etc are only simple classes and don't have subclasses, you could use getClass() instead of specifying an explicit parameter, as suggested by Scott.

网友答案:

If you're using this in a DAO, I tend to initialize it with the class. So maybe

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();     
    }
  }
}
网友答案:

You can use an enum to conceal this:

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");
分享给朋友:
您可能感兴趣的文章:
随机阅读: