2014-09-22 51 views
2

我有一个是通过下面的类来表示两个数据模型:我可以在这里申请里氏替换原则

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 - 一个对象,它类似于第一但具有下列限制: 它可以存储2D图像仅具有沿x和y轴相同的x轴,y轴和尺寸。

在这种情况下推导出3DImageImagesSet? 从我的角度来看3DImage“是”ImagesSet(但有小的限制) 我可以在这里适用Liskov替代原则吗?

在这种情况下,如果我们试图添加一个图像与另一个x,y轴 - 方法AddImage要么会抛出异常或返回错误。

由于提前, 谢尔盖

回答

4

我maxim1000同意LSP将被侵犯,因为派生类补充说,不存在基类限制。如果你仔细看看你的描述,你会注意到这个问题可以颠倒过来:ImageSet可以从3DImage派生吗?

您的情况与Ellipse-Circle问题有些相似。哪一个来自另一个?圆是一个有约束的椭圆,或者是一个椭圆又是一个有额外半径的圆?重点是两者都是错误的。如果将椭圆限制为等于半径,则尝试设置不同值的客户端将收到错误。否则,如果我们说椭圆只是一个较少的约束圆,我们会得到一个更微妙的错误。假设形状不能突破屏幕边界。现在假设一个圆被替换为一个椭圆。根据测试的坐标,形状可能会突破屏幕区域而不改变客户端代码。这是LSP的确切违反。

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

+1

顺便说一句,这个问题只发生在Circle和Ellipse的可变接口上。如果我们在它们的接口中只有读取方法,那么可以从椭圆派生圆(如果它有用的话)。 – maxim1000 2014-09-23 14:45:22

4

可能这只是我,但每当我听到“得到或没有得到”我的第一反应“未获得” :)在这种情况下

两个原因:

  1. 由于这些“小限制”,LSP被违反了。因此,直到您的基类中有AddImage,允许以任何方向添加图像,3DImage而不是ImagesSet。算法没有办法说明他们需要这个特性(并且评论不是一个好的地方:)),所以你必须依靠运行时检查。用这种方式编程仍然是可能的,但这对于开发人员来说会是一个额外的开销。

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

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

0

尊敬的maxim1000和sysexpand,

感谢您的答案。我赞同你。现在很清楚LSP是违反的,在这种情况下,我不能从ImagesSet派生出3D图像

我需要重新设计以下面的方式将溶液:

2DImage将包含:

  • 2DDimension
  • PixelSize(单位mm)
  • 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不受侵犯。