Adapter Pattern vs Liskov Substitution
适配器设计模式用于将类(目标)的接口转换为客户机期望的另一个接口(适配器)。适配器允许不兼容的类一起工作,否则由于它们的接口不兼容而无法一起工作。
适配器模式可以通过两种方式实现:继承(适配器模式的类版本)和组合(适配器模式的对象版本)。
我的问题是关于使用继承实现的适配器模式的类版本。
以下是绘图编辑器的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | interface Shape { Rectangle BoundingBox(); Manipulator CreateManipulator(); } class TextView { public TextView() { } public Point GetOrigin() { } public int GetWidth() { } public int GetHeight() { } } interface Shape { Rectangle BoundingBox(); Manipulator CreateManipulator(); } class TextView { public TextView() { } public Point GetOrigin() { } public int GetWidth() { } public int GetHeight() { } } |
我们希望重用textview类来实现textshape,但是接口是不同的,因此,textview和shape对象不能互换使用。
应该更改textView类以符合形状接口吗?也许不是。
textShape可以通过以下两种方式之一使textView接口适应形状的接口:
类适配器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | interface Shape { Rectangle BoundingBox(); Manipulator CreateManipulator(); } class TextView { public TextView() { } public Point GetOrigin() { } public int GetWidth() { } public int GetHeight() { } } class TextShape : TextView, Shape { public Rectangle BoundingBox() { Rectangle rectangle; int x, y; Point p = GetOrigin(); x = GetWidth(); y = GetHeight(); //... return rectangle; } #region Shape Members public Rectangle Shape.BoundingBox() { return new TextBoundingBox(); } public Manipulator Shape.CreateManipulator() { return new TextManipulator(); } #endregion } |
现在回答问题:—)。textShape继承自shape,尤其是textView,是否是有效的"is a"关系?如果不是,这是否违反了里斯科夫的替代原则?
它不会违反Liskov替换原则,除非子类中有一些东西使它的行为对超类没有意义(违反了超类的契约)。当然,这是不完整的代码,但我看不到任何迹象。
它可能违反了单一责任原则,但我不确定在适配器实现中这是一个巨大的问题。
我一般更喜欢代表的方式。