我已经遇到了以下几点:对象组合优于类继承的优点.但是我经常在许多文章中看到以下句子
In object composition,functionality is acquired dynamically at run-time by objects collecting references to other
objects. The advantage of this approach is that implementations can be replaced at run-time. This is possible because
objects are accessed only through their interfaces,so one object can be replaced with another just as long as they
have the same type.但怀疑可能是天真的,因为我是初学者.如何在运行时可以替换实现?如果我们编写新的代码行,我们不需要编译来反映变化?那么什么意思是在运行时替换?相当混乱
或任何其他魔术,幕后活动发生.任何人都可以回覆.
解决方法
想一下Stack的一个实现. Stack的简单实现在幕后使用列表.天真地,你可以扩展ArrayList.但是现在,如果你需要一个单独的由LinkedList支持的Stack,你将需要有两个类:ArrayListStack和LinkedListStack. (这种方法也有一个缺点,即在Stack上暴露List方法,这违反了封装).
如果您使用组合,则可以由调用者提供Back to Stack的列表,您可以使用一个可以使用LinkedList或ArrayList的Stack类,具体取决于用户所需的运行时特性.
简而言之,实现“在运行时更改”的能力不是指能够在运行时更改其实现的类的实例,而是类在编译时不知道它的精确实现将是什么.
还要注意,使用组合的类不需要允许在运行时(由调用者)选择委托实现.有时这样做会违反封装,因为它会给调用者更多关于类的内部信息,而不是所需的.在这些情况下,组合仍然具有仅暴露抽象方法的好处,并允许在稍后的修订中更改具体实现.
现实生活中的例子
顺便说一下,我使用Stack的例子,因为它不是纯粹假设的.实际上,Java’s Stack class扩展了Vector,它使得它永远携带同步的行李和一个数组支持列表的性能特征.因此,使用该类是非常不鼓励的.
也可以在07年1月的Java库中找到正确使用组合的完美示例.由于任何Map可以用于表示Set(通过使用虚拟值),所以该方法返回一个由传入地图.返回的Set然后继承了它所包含的Map的特性,例如:可变性,线程安全性和运行时性能,而无需为ConcurrentHashMap,ImmutableMap,TreeMap等创建并行Set实现.