当然可以,但是我们称其为组成和授权。策略模式和依赖注入在结构上看似相似,但目的不同。
策略模式允许在同一界面下对行为进行运行时修改。我可以告诉野鸭飞翔,看着它飞翔。然后将其换成喷气飞行员鸭,并与达美航空公司一起观看它的飞行。在程序运行时执行此操作是一种策略模式。
依赖注入是一种避免硬编码依赖的技术,因此依赖可以独立更改,而无需在更改客户端时对其进行修改。客户只是表达他们的需求,而不知道如何满足他们。因此,如何满足它们是在其他地方(通常在主要方面)决定的。您不需要两只鸭子就可以使用此技术。只是使用鸭子而又不知道或不在意哪只鸭子的东西。不会造鸭或去寻找它的东西,但是非常乐意使用您将其交给鸭的任何东西。
如果我有一个具体的鸭子课程,我可以让它实现它的飞行行为。我什至可以根据状态变量将行为从双翼飞行切换为带三角洲飞行。这个变量可以是一个布尔值,一个int值,也可以是一个FlyBehavior
具有fly
执行任何飞行样式的方法的,而无需我用if对其进行测试。现在,我可以更改飞行样式,而无需更改鸭子的类型。现在,绿头鸭可以成为飞行员。这就是组成和授权。鸭子由FlyBehavior组成,可以将飞行请求委托给它。您可以通过这种方式一次替换所有的鸭子行为,或者为每种行为或两者之间的任何组合保留某种东西。
这给您除继承之外所有与继承相同的权力。继承使您可以表达在Duck子类型中要覆盖的Duck方法。组合和委派要求Duck从一开始就明确委派给子类型。这要灵活得多,但是需要更多的键盘输入,Duck必须知道它的发生。
但是,许多人认为必须从一开始就明确设计继承。而且,如果还没有这样做,则应将类标记为封闭/最终禁止继承。如果您采用这种观点,那么继承与组合和委派相比确实没有任何优势。因为那样的话,您要么必须从一开始就设计可扩展性,要么以后愿意将其分解。
拆掉东西实际上是一个受欢迎的选择。请注意,在某些情况下这是个问题。如果您已经独立部署了不打算在下一个发行版中进行更新的库或代码模块,那么最终可能会遇到无法了解您最新知识的类版本。
虽然以后愿意拆掉东西可以使您摆脱设计的束缚,但是对于能够使用鸭子的东西进行设计而不必知道鸭子在使用时实际会做什么的事情,有一些非常强大的功能。那不知道是有力的东西。它使您可以暂时停止思考鸭子,而思考其余的代码。
“我们可以”和“我们应该”是不同的问题。优先考虑继承而不是不使用继承。在某些情况下,继承最有意义。我将向您展示我最喜欢的示例:
public class LoginFailure : System.ApplicationException {}
继承使您可以仅在一行中创建具有更具体的描述性名称的异常。
尝试通过合成来做到这一点,您会一团糟。同样,也没有继承溜溜球问题的风险,因为这里没有可重用和鼓励继承链的数据或方法。这一切都是一个好名字。永远不要低估好名声的价值。
Duckbehavior.quackBehavior
您的代码中“字段”和“其他字段” 的类型是什么?