Помогите создать универсальный класс, чтобы избежать дублирования кода - PullRequest
3 голосов
/ 03 декабря 2009

У меня есть простая проблема, попытайтесь остаться сухим, используя Appengine.

Указанные ниже 2 функции идентичны, за исключением объекта, отправляемого в качестве параметра. На самом деле у меня 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.

Любое хорошее предложение, как сделать это без дублирования?

Спасибо. Daniel

Ответы [ 6 ]

4 голосов
/ 04 декабря 2009

Возможно, это не самый простой способ сделать что-то, но я не могу помочь, но думаю, что это будет иметь смысл в долгосрочной перспективе.

Создать интерфейс

// 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 .

4 голосов
/ 03 декабря 2009

Вам не нужны генерики для этого; используйте thing.getClass ():

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

(вы должны добавить туда нулевую проверку на случай, если переданный параметр был нулевым)

[Примечание: я изменил свой ответ сразу после того, как опубликовал его, когда понял, что здесь не нужны генерики ...]

2 голосов
/ 04 декабря 2009

СУХОЙ - хороший принцип. Как и 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());

Поскольку это пустой метод, а PersistenceManager не работает с универсальными типами, я бы посоветовал избегать использования универсальных типов. Этот метод, если применимо, имеет дополнительный бонус, который вам не понадобится изменять иерархию типов Product, Person и т. Д.

Недостатком является то, что если этот метод вызывается из нескольких мест, может быть много мест для изменения подписи - но легко позволить компилятору выяснить, сколько времени это займет.

2 голосов
/ 03 декабря 2009

Самый простой способ - ввести тип в качестве параметра:

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() вместо указания явного параметра, как предлагает Скотт.

1 голос
/ 04 декабря 2009

Если вы используете это в 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();     
    }
  }
}
0 голосов
/ 29 января 2010

Вы можете использовать enum, чтобы скрыть это:

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");
...