我可以在这里申请Liskov替代原则

时间:2014-09-22 11:39:16

标签: oop design-patterns object-oriented-analysis

我有两个数据模型,由以下类表示:

1) ImagesSet - 拥有 2DImage 的对象,每个 2DImage 都有自己的位置(原点( 3DPoint ),x轴,y轴( 3DVector )和沿x和y轴的尺寸(以像素为单位)),但像素尺寸相同(以mm为单位),角度在x和y轴之间(90度)

此对象具有以下方法(伪代码):

  • AddImage(2DImage);
  • RemoveImage(的ImageIndex);
  • number GetNumberOfImages();
  • 2DImage Get2DImage(ImageIndex);

2) 3DImage - 与第一个类似但具有以下限制的对象: 它只能存储沿x轴和y轴具有相同x轴,y轴和尺寸的2D图像。

在这种情况下从 ImagesSet 派生 3DImage 是否正确? 从我的观点来看, 3DImage "是一个" ImagesSet (但限制较少) 我可以在这里申请利斯科夫替代原则吗?

在这种情况下,如果我们尝试使用另一个x,y轴添加图像 - 方法 AddImage 将引发异常或返回错误。

提前致谢, 塞吉

3 个答案:

答案 0 :(得分:4)

可能只是我,但每当我听到"派生或不派生"我的第一反应"没有衍生出来" :)

在这种情况下有两个原因:

  1. LSP完全违反了这些"小限制"。因此,在基类中AddImage允许添加任意方向的图像之前,3DImage ImagesSet。算法无法表明他们需要此功能(并且评论不是一个好地方:)),因此您必须依赖运行时检查。它仍然可以用这种方式编程,但这对于开发人员来说将是一个额外的开销。

  2. 每当你创建一些抽象时,理解为什么要创建它是很重要的。通过派生,您可以隐式地创建一个抽象 - 它是3DImage的接口。而不是这样,明确地创建这个抽象更好。创建一个接口类,列出那些对能够处理这两种数据结构的算法有用的方法,并使实现该接口的ImagesSet3DImage可能添加一些其他方法。

  3. P.S。 可能AddImage将成为这些添加方法之一 - ImagesSet3DImage不同,但这取决于......

答案 1 :(得分:4)

我同意maxim1000将违反LSP,因为派生类添加了基类中不存在的限制。如果你仔细看看你的描述,你会发现问题可以颠倒过来:ImageSet可以从3DImage派生吗?

您的情况与Ellipse-Circle问题有些类似。哪一个来自另一个?圆是带有约束的椭圆,还是椭圆是带有额外半径的圆?关键是两者都是错的。如果将椭圆约束为相等的半径,则尝试设置不同值的客户端将收到错误。

否则,如果我们说椭圆只是一个不太受约束的圆圈,我们会得到一个更微妙的错误。假设形状可能不会破坏屏幕的边界。现在假设用椭圆代替圆。根据测试的坐标,形状可能会突破屏幕区域而不更改客户端代码。这确实违反了LSP。

结论是 - 圆和椭圆是分开的类; 3DImage和ImageSet是单独的类。

答案 2 :(得分:0)

亲爱的maxim1000和sysexpand,

感谢您的回答。我同意你的看法。现在很明显违反了LSP,在这种情况下,我无法从 ImagesSet 派生 3DImage

我需要按以下方式重新设计解决方案:

2DImage 将包含:

  • 2DDimension
  • PixelSize (以毫米为单位)
  • PixelData取出

2DImageOrientated 将派生自 2DImage ,并将包含新数据:

  • 3DPoint 来源,
  • 3DVector x-,y轴

我将创建纯接口 IImagesSet

  • 编号GetNumberOfImages()
  • RemoveImage(的的ImageIndex
  • 2DImageOrientated Get2DImage()

ImagesSet 将来自 IImagesSet ,并将包含以下内容:

  • 矢量<的 2DImageOrientated >
  • Add2DImage(的 2DImageOrientated
  • 编号GetNumberOfImages()
  • RemoveImage(的的ImageIndex
  • 2DImageOrientated Get2DImage()

3DImage 也将来自 IImagesSet ,并将包含以下内容。

  • 矢量<的 2DImageOrientated >
  • Add2DImage( 2DImage
  • SetOrigin(的 3DPoint
  • SetXAxis(的 3DVector
  • SetYAxis(的 3DVector
  • 编号GetNumberOfImages()
  • RemoveImage(的的ImageIndex
  • 2DImageOrientated Get2DImage()

在这种情况下,我认为LSP没有被违反。