开闭原则是不是意味着我们必须将每个方法都定义为虚拟的?
Posted
技术标签:
【中文标题】开闭原则是不是意味着我们必须将每个方法都定义为虚拟的?【英文标题】:Does Open Closed Principle mean that we have to define every method as virtual?开闭原则是否意味着我们必须将每个方法都定义为虚拟的? 【发布时间】:2019-04-01 23:14:16 【问题描述】:我很难理解开放封闭原则背后的想法。
据我所知,原则是每个类都应该关闭修改,打开扩展。对吧?
这意味着我们必须将类中的每个方法都设为虚拟,这样我们就可以扩展类而无需修改它。这是正确的吗?
【问题讨论】:
“应该”!=“必须”。这意味着,如果您希望该方法成为扩展点 - 扩展应该在不修改基类的情况下发生。如果方法不打算成为扩展点 - 它不应该是虚拟的。更进一步——如果一个类没有被设计成一个扩展点——它应该是final
(默认)。
@zerkms 假设您有一个插件,您不知道您的用户将如何使用/扩展它。除了您知道覆盖它们可能会破坏功能的方法之外,将每个方法都设为虚拟方法是否正确?
“你不知道你的用户将如何使用/扩展它”——你不能为未知而设计:每一种扩展的方式都应该是已知的并记录在案。如果您设计的所有方法都是可扩展的并且您的代码支持它 - 确实让它们成为虚拟的。 “除了你知道覆盖它们可能会破坏功能的那些?” --- 我会说相反。
【参考方案1】:
我认为您对开闭原则的含义有些误解。
开放-封闭原则指出软件实体应该对修改关闭,对扩展开放。本文中的软件实体是指类、结构体方法等。
基本思想是您的实体不需要经常更改需求。如果出现新要求,您的实体应扩展以适应新功能。
假设我们有以下函数:
public List<Product> GetProducts(Criteria criteria)
return context.Where(x => x.criteria1 = criteria.criteria1)
.Where(x => x.criteria2 = criteria.criteria2)
.Where(x => x.criteria3 = criteria.criteria3)
.Where(x => x.criteria4 = criteria.criteria4);
很容易看出,当另一个标准要求出现时,这将需要修改“ProductRepository”类及其功能。当然,这个类中的更多函数可能需要修改,因为它也可能使用标准对象。
假设我们可以这样写:
private List<Product> GetProducts(Criteria criteria)
return cleverContext.Apply(criteria);
我们立即获得了只修改或扩展负责标准的代码的灵活性。
改进设计以满足开闭原则的最大方法是使用富域。当您的域对企业业务规则进行建模时,这些规则永远不会改变。我们将域与用例分开来处理应用程序规则。
鲍勃叔叔在他干净的架构中写了更多关于这方面的文章。
如果有什么我可以解释的,请告诉我,或者尝试进一步解释:)
【讨论】:
所以如果我理解正确的话,如果你正确应用了OCP,当有新的需求进来时,你只需要修改与那个需求对应的部分代码。因此,其他类的修改被最小化。对吗? @MoNarimani 没错。从架构的角度来看,如果企业规则发生变化,您的域也应该发生变化。当您的应用程序规则发生变化时,用例应该会发生变化。要理解的关键概念是扩展并不一定意味着继承。它可以指作文,而且更常见。当您的对象易于重用时,它们定义了一个目标,并且只有一个业务理由需要更改。这确保了其他类需要最少的修改。以上是关于开闭原则是不是意味着我们必须将每个方法都定义为虚拟的?的主要内容,如果未能解决你的问题,请参考以下文章