You could declare DaoFactory as follows:
public interface DaoFactory<D extends Dao<? extends MyObject>> {
<T extends MyObject> D getDao(Class<T> type);
}
Then, JsonDaoFactory could be implemented as follows:
public class JsonDaoFactory implements DaoFactory<JsonDao<? extends MyObject>> {
private final Map<Class<? extends MyObject>, JsonDao<? extends MyObject>> daos =
new HashMap<>();
public JsonDaoFactory() {
daos.put(Contact.class, new JsonContactDao());
daos.put(Customer.class, new JsonCustomerDao());
}
@Override
@SuppressWarnings("unchecked")
public <T extends MyObject> JsonDao<T> getDao(Class<T> type) {
return (JsonDao<T>) daos.get(type);
}
}
I've used a Map to make every descendant of MyObject match its corresponding JsonDao (here I've used Contact and Customer, and JsonContactDao and JsonCustomerDao, respectively). I've suppressed an unchecked cast warning because I'm explicitly filling the map in the constructor, so I'm sure there won't be a ClassCastException.
For completeness, here's the code for SqliteDaoFactory:
public class SqliteDaoFactory implements DaoFactory<SqliteDao<? extends MyObject>> {
private final Map<Class<? extends MyObject>, SqliteDao<? extends MyObject>> daos =
new HashMap<>();
public SqliteDaoFactory() {
daos.put(Contact.class, new SqliteContactDao());
daos.put(Customer.class, new SqliteCustomerDao());
}
@Override
@SuppressWarnings("unchecked")
public <T extends MyObject> SqliteDao<T> getDao(Class<T> type) {
return (SqliteDao<T>) daos.get(type);
}
}
The code for both factories is almost duplicated, but I couldn't find a way to solve this.
Here's how to use these factories:
JsonDaoFactory jsonDaoFactory = new JsonDaoFactory();
JsonDao<Contact> contactJsonDao = jsonDaoFactory.getDao(Contact.class);
JsonDao<Customer> customerJsonDao = jsonDaoFactory.getDao(Customer.class);
SqliteDaoFactory sqliteDaoFactory = new SqliteDaoFactory();
SqliteDao<Contact> contactSqliteDao = sqliteDaoFactory.getDao(Contact.class);
SqliteDao<Customer> customerSqliteDao = sqliteDaoFactory.getDao(Customer.class);
T<U>.interface DaoFactory<U extends MyObject, T extends Dao<U>>?