2

在浏览我刚加入的新公司的代码库时,我发现了一些我以前从未想过的东西。基本上会发生这种情况:我们有一个基类,它表示一个 Image ,它有几个抽象方法来在不同的图像类型之间进行转换。不同的图像类型是基本 Image 类的子类。子类负责在都是派生类的不同图像之间进行转换。

我的问题是这应该是一个好的设计吗?如果不是,我们还有什么选择?

非常感谢。

4

2 回答 2

1

如果我设计了场景,那么我会做以下事情。(注意我不是一个很好的设计师,只是分享我的概念)

  1. 具有抽象方法的基类图像,仅表示行为而不是任何要转换的操作
  2. 实现那些定义行为的抽象类的子类
  3. 其他具有在不同图像之间转换的方法的实用程序类。
于 2013-10-07T13:56:44.013 回答
1

它不是最优雅的结构,但它可以工作——只要您只处理几种图像类型。将转换转换为通用基类的通用功能会更优雅,并且更易于扩展到其他图像类型。缺点是引入了变化,并带来了一些设计上的权衡。

关键的架构问题是:

  1. 在哪里?你把关于如何将 X 型转换为 Y 型的知识放在哪里?X型里面?Y型里面?在一个共同的祖先里面?或者在一些单独的转换设施内?
  2. 如何?X 应该知道如何直接导出到 Y 吗?或者 Y 应该知道如何从 X 导入?还是应该 X 导出为通用/通用格式,然后 Y 知道如何从中导入?

您可以在野外找到这些选项中的每一个。

您当前的设计,在每个图像类中都有转换,反映了许多语言中相当基本的数据类型/类;他们每个人都应该能够序列化、表示或将自己转换为其他几种格式(例如,转换为字符串,转换为像 pickle 这样的网络格式等)。但是如果类型多于几种,编写从 X 到 Y 的转换器将很快变得难以管理。您将需要 n(n-1) 种转换方法——“没有人有时间去做!”

另一方面,像netpbmpandoc这样的全能转换和操作套件通常使用通用的中间表示。我所知道的与您的情况最接近的类似物,像Python 的 PIL/Pillow这样的成像库,通常定义一个通用基类(例如Image),它扮演通用格式/数据模型的角色,即使它们没有自己的 on-磁盘格式。

抽象总是不完美的。当您只处理 X 或 Y 时,继承是花花公子。但是当您需要同时处理 X 型和 Y 型的错综复杂,没有完美的答案。用进一步的类分解无济于事;多重继承也不会。

范式和可能最好的整体答案是将转换向上移动到基类。但这并非没有它自己的权衡。然后,基类必须了解并适应所有可能的子类的转换。因此,即使您正在转换没有 Alpha 通道、CLUT、Z 缓冲区、伽马校正表、HDR 校准信息和其他数据/元数据的格式,基类方法和数据结构也必须了解和处理如果有的话他们的子类有那些东西。将转换向上推送还可能导致基类和子类之间的乒乓对话(在设计和运行时),因为基方法试图询问子类或将任务委托给子类。但是,这些关于住房转换的担忧是次要问题。它们并不太令人烦恼——除非并且直到你真正遇到它们。

所以网络建议是:对于少数图像类型,转换可以合理地存在于每个图像类中。如果您已经拥有“一只鸟在手”——已经采用这种方法的工作、测试代码,则尤其如此。但是,如果您想“清理”设计,将导入/导出/转换转换为基类会更优雅,并且更适合其他图像类型。(在开始之前,请确保您对现有实现进行了良好的单元测试,以便您可以轻松地验证第二代代码。)

于 2013-10-07T16:09:05.683 回答