我们创建了一个“进程监视器”类,争论从这里开始:
他说构造函数只应接受字符串(比如"iexplore.exe"),而我则认为我们应该继承“进程监视器”来创建一个“浏览器监视器”,它接受当前使用的浏览器枚举,构造函数将把它“翻译”成“iexplore.exe”。 他说我们应该使用一个实用函数作为翻译器。
我知道两种方式都是有效的和好的,但我想知道每种方式的优缺点以及在我们的情况下哪种更合适。
最近,我采取的方法是“现在保持简单,如果需要扩展再进行重构。”
你现在正在做的似乎相当简单。你只需要处理一个情况。所以我建议现在采用更简单的方法。最终,如果你从来不需要再创建另一种类型的监视器,则可以避免额外的复杂性。但要以一种容易重构的方式编码。
将来,如果你发现需要另一种类型的监视器,请花费精力将其重构为继承(或组合,或其他模式)。如果初始代码编写正确,重构应该相对容易,因此你并没有增加太多额外的工作量。
我发现这种方法对我来说相当有效。在我真正不需要继承的情况下,代码保持简单。但当我真正需要时,我可以轻松添加它而没有任何实际的问题。
其他条件相同的情况下,我更喜欢简单的解决方案(一个以字符串为构造函数参数的具体类)而不是更复杂的方案(使用基类和子类)。
当您想要改变行为时,继承是适当的:如果浏览器监视器将执行一些普通进程监视器不会执行的操作。但是,如果您只想改变数据的值,则只需改变数据即可。
这取决于您的使用情况或您所追随的神。
我不会说“继承是邪恶的”,但通常我遵循“优先选择组合而非继承”的原则,以避免过多的类层次结构。
用非常简单的语言来说:
当你需要使用继承(子类化)时,子类具有与超类不同的行为(而不是属性)。
我认为在大多数情况下,简单胜过复杂是一个好策略,只要你的简单不是太短视(参考Herms的建议,在编写代码时要以便于后期重构为目标)。
然而,我也知道要消除脑海中那个鼓励更彻底设计的错误思想是多么困难。如果你仍然想支持继承,但不一定要考虑“基类”和“子类”,你可以简单地定义一个接口(例如IProcessWatcher),由ProcessWatcher实现。当你使用ProcessWatcher对象时,用接口来引用它,这样如果你以后决定创建一个BrowserWatcher(或任何其他类型的ProcessWatcher),只要它实现了IProcessWatcher接口,就不必强制它从ProcessWatcher派生。
警告:请谨慎操作。很容易想要为每个对象定义一个接口,但我们必须面对这是荒谬的事情。=)
最终,你需要找到一些你们都感到舒适的东西,因为你们两个都必须维护这段代码,我认为这可能是一个不错的妥协方案,而不仅仅是“继承还是不继承”的问题。
祝你好运!