因此,我有我的应用程序公开的这个公共(public) 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
有一些不应公开的属性——比如数据库 ID。我目前正在做的是这样的:
/** 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
。 -like objects instead necessarily 解决问题。
我唯一能想到的就是将内部 key 和外部 key 完全分开,并保持 Map<Key, InternalKey>
左右。 .但在那种情况下,我必须要么复制违反 DRY 的元数据,要么拥有外部 Key
委托(delegate)给 InternalKey
, 在这种情况下 Map
违反了 DRY。
谁能想出更聪明的办法?
最佳答案
我见过的一种方法是为所有对象(在本例中为键)公开一个通用接口(interface),并提供一个基本实现,该实现只为每个方法抛出 UnsupportedOperationException
(或什么也不做)。然后子类实现随后覆盖方法以提供功能。虽然它不是很像 OO,但您会在 JDK API 中找到一些示例(例如 Iterator
的 remove()
方法)。
另一种选择:您可以使用 visitor让每个对象在不向下转换的情况下执行功能的模式;例如
public interface KeyVisitor {
void visitInternalKey(InternalKey k);
void visitFooBarKey(FooBarKey k);
}
public interface Key {
void visit(KeyVisitor kv);
}
public class InternalKey implements Key {
public void visit(KeyVisitor kv) {
kv.visitInternalKey(this);
}
}
此处的缺点是您必须在 InternalKey
上公开方法(至少通过接口(interface))以允许访问者实现调用它们。但是,您仍然可以在包级别保留实现细节。
关于java - 将公共(public) API 转换为内部胶水代码时避免强制转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1245117/