这听起来像是Strategy 模式的一个很好的应用程序。
您将创建一个抽象基类FileFormat(策略接口),其中包含两个虚函数projectToXml 和xmlToProject,它们应该将您的内部项目表示转换为XML,反之亦然。
然后创建两个实现子类FileFormatNew 和FileFormatLegacy(这些是具体策略)。
然后,您的保存函数将额外需要一个 FileFormat 实例,并调用该对象的相应方法来进行数据转换。您的加载函数可以通过检查 XML 树来选择要使用的策略,以了解它是哪个版本。
当您需要支持另一种文件格式时,您只需创建一个新类,它是 FileFormat 的子类。
cmets交流后的补充
当您将拥有许多差异很小的版本并且您仍想使用策略模式时,您可以将 FileFormat 制作为多种策略的组合:CircleStragegy、RectangleStrategy、LineStrategy 等。在这种情况下,我不会为不同版本的 FileFormat 使用不同的类。我将为每个版本创建一个静态工厂函数,该函数返回一个 FileFormat 以及该版本中使用的 Strategy 对象。
FileFormat FileFormat::createVersion1_0() {
return new FileFormat(
new LineStrategyOld(),
new CircleStrategyOld(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_1() {
// the 1.1 version introduced the new way to save lines
return new FileFormat(
new LineStrategyNew(),
new CircleStrategyOld(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_2() {
// 1.2 uses the new format to save circles
return new FileFormat(
new LineStrategyNew(),
new CircleStrategyNew(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_3() {
// 1.3 uses a new format to save rectangles, but we realized that
// the new way to save lines wasn't that good after all, so we
// returned to the old way.
return new FileFormat(
new LineStrategyOld(),
new CircleStrategyNew(),
new RectangleStragegyNew()
);
}
注意:在实际代码中,您当然会为策略类名称使用比“旧”和“新”更多的描述性后缀。