Итак, у меня есть этот публичный API, который выставляет мое приложение, позволяя клиентам писать плагины. Для примера давайте предположим, что это довольно простая система пар ключ-значение, что-то вроде:
public interface Key {
// marker interface, guaranteed unique in some scope
}
public interface KVPService {
Set<Key> getKeys();
Object getValue(Key k); // must be a key provided by getKeys() or it blows up
}
Теперь давайте скажем, что внутри Key
есть некоторые атрибуты, которые не должны быть представлены, например, идентификатор базы данных. То, что я сейчас делаю, выглядит примерно так:
/** Internal impl of external Key */
class InternalKey implements Key {
int getDatabaseId() {
// do something...
}
}
/** Internal impl of external KVPService */
class InternalKVPService implements KVPService {
// ...
public Object getValue(Key k) {
InternalKey ik = (InternalKey) k;
return getValueFromDBOrWherever(ik.getDatabaseId());
}
// ...
}
Это кажется не идеальным. Есть ли способ, которым я могу перераспределить обязанности, чтобы избежать приведения и сохранить внутреннюю / внешнюю инкапсуляцию?
Обратите внимание, что в реальном мире это немного сложнее, чем это; к Key
эквивалентам прикреплено немало метаданных, и есть ряд вещей, которые кто-то может захотеть сделать друг с другом, кроме получения простого значения, поэтому простое экспонирование, скажем, Map.Entry
-подобных объектов вместо обязательно решить проблему.
Единственное, что мне удалось придумать, - это полностью отделить внутренний и внешний ключи и сохранить около Map<Key, InternalKey>
. Но в этом случае я должен был бы либо скопировать метаданные, которые нарушают DRY, либо иметь внешний делегат Key
для InternalKey
, и в этом случае Map
нарушает DRY.
Кто-нибудь может придумать что-нибудь более умное?