1

我有一组应用程序都需要与网络服务同步:

  1. 从 Web 服务下载一些 XML。
  2. 解析那个 XML。
  3. 然后更新数据库以匹配解析的 XML。

我想将尽可能多的相关代码保留在一个通用库中以避免重复,并且我想让不同的应用程序都将它们的解析和更新代码放入一个相当简单的通用框架中。

所以有一个常见的sync()方法:

public void sync(URI updateUrl, XMLParser parser, Updater animalUpdater) {
    String raw = getXML();
    List<ParsedAnimal> parsed = parser.parse(raw);
    // try:
    // begin transaction
    for (ParsedAnimal pi : parsed) {
        animalUpdater.updateItem(pi);
    }
    // commit transaction
    // catch: rollback transaction, rethrow
    // finally: close database connection
}

解析器返回 ParsedCat 或 ParsedDog 或其他任何东西,所有这些都继承自一个公共 ParsedAnimal 类:

public abstract class ParsedAnimal {...}
public class ParsedCat extends ParsedAnimal {...}
public class ParsedDog extends ParsedAnimal {...}

然后我有一个更新程序,它需要获取已解析的项目并将内容注入数据库:

public abstract class Updater {
    public abstract void updateItem(ParsedAnimal parsed);
}
public class CatUpdater extends Updater {
    @Override
    public void updateItem(ParsedCat parsed) {}
}
public class DogUpdater extends Updater {...}

这不起作用——Updater 的合同规定 updateItem() 接受 ParsedAnimal,而 CatUpdater 和 DogUpdater 都通过只接受特定类型的动物来打破该合同。

我拥有的是一个并行的类层次结构——ParsedX 与 XUpdater 一对一匹配。Coding Horror 上的Code Smells页面建议将两个类层次结构合并到一个层次结构中,但我觉得“正在处理的东西”和“正在工作的东西”足够不同,它们应该是单独的类。

有没有一种简洁的方式来构建它,或者一些可以派上用场的设计模式?

4

2 回答 2

4

Updater泛型可以为您的合同问题派上用场:

public abstract class Updater<T extends ParsedAnimal> {
    public abstract void updateItem(T parsed);
}
public class CatUpdater extends Updater<ParsedCat> {
    @Override
    public void updateItem(ParsedCat parsed) {}
}
public class DogUpdater extends Updater<ParsedDog> {...}

但是,您的sync方法有一个Updater作为参数,它尝试将其用于所有已解析的项目。这行不通。如果您将有一个单独的Updater每个解析类型,您需要根据您拥有的解析结果来实例化更新程序。这可以通过某种形式的“工厂”来处理。首先,您可能想看看使用工厂方法模式。

于 2012-10-29T00:20:46.297 回答
0
updateItem(ParsedAnimal parsed){
    if (parsed instanceof ParsedCat) {
        ... 
    } else if (parsed instanceof ParsedDog) {
        ... 
    } 
} 
于 2012-10-29T00:23:56.860 回答