java - 将公共(public) API 转换为内部胶水代码时避免强制转换

标签 java oop encapsulation

因此,我有我的应用程序公开的这个公共(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 中找到一些示例(例如 Iteratorremove() 方法)。

另一种选择:您可以使用 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/

相关文章:

java - 有没有办法继承Hibernate的@Where注解?

java - 如何从另一台计算机上的独立客户端通过互联网调用在远程计算机上运行的 EJB,而无需 JSP/Servlet 作为中间层?

对象外的JavaScript函数封装

c++ - 在这种情况下如何保持良好的数据封装?

model-view-controller - 俄罗斯方 block 和漂亮的图形

java - 如何在 JBOSS AS 启动时查找特定服务是否运行/启动?

Javafx onMouseclicked 上

c# - 如何使用 XmlSerializer 序列化内部类?

php - 简单解释 PHP OOP vs Procedural?

c++ - 在类中使用C++返回子字符串