最佳答案将取决于这些类的用例和环境。作为开发应用程序或框架的团队的一部分,采用该团队使用的设计模式比寻求“完美”的解决方案更可取,因为它会使其他人更容易采用和维护您的代码。
您期望如何使用和扩展这些类也很重要。您认为“Square”将来需要可移动吗?Shape 的可移动性总是静态的,还是作为动态属性更有用?Move() 对非 Shapes 的类有任何价值吗?如果可移动性可用作动态属性,请考虑:
public abstract class Shape
{
public bool isMovable()
{
return false;
}
public virtual void Move()
{
if (!isMovable() {
throw new NotSupportedException();
} else {
throw new BadSubclassException();
}
}
}
然后,您的子类可以覆盖 isMovable 以提供静态或动态行为,并且可以随着时间的推移进一步修改或子类化,只要您的文档明确说明 isMoveable 应该始终在调用 Move 之前。默认行为应该基于您期望使用您的代码的其他人的期望,基于他们如何实现相关的设计模式。
通过查看集合类的可变性在不同框架中如何演变的历史,可以找到做出这些决定所面临挑战的一个很好的例子。有些设计将可变类(集合、数组、字典等)作为基类,在子类中实现不变性,反之亦然。这两种方法以及动态方法都有有效的论据,但对于框架的用户来说,最重要的因素是一致性,因为正确的实际上是最容易使用的问题,提供安全性和性能不是妥协。