类继承和对象组合是面向对象系统中功能复用的两种常用技术。
类继承:根据其他类的实现来定义一个类的实现,生成子类,又称白箱复用;
对象组合:新的更复杂的功能可以通过组装或组合对象来获得,要求被组合的对象具有良好定义的接口,又称黑箱复用。
注意,这里的黑箱和白箱是相对可视性而言的,即,在继承方式中,父类的内部细节对子类可见,而在组合的复用方式里,对象的内部细节是不可见的。
继承:
- 优点:在编译时刻静态定义的,且可直接使用;
- 缺点:无法在运行时刻改变从父类继承的实现,父子类之间紧依赖,破坏封装性。
组合:
- 优点:运行时刻动态定义,(由于对象只能通过接口访问),不破坏封装性;
- 缺点:接口定义需详细严格。
相对而言,组合更为理想,面向对象设计一大原则是:优先使用对象组合,而不是类继承。
接下来我们来聊聊委托。委托是组合方法的一种,它使得组合具有与继承同样的复用能力。在委托方式下,有两个对象参与处理一个请求,接受请求的对象将操作委托给它的代理者,类似于子类将请求交予父类处理,而使用继承时,被继承的操作总能引用接受请求的对象,委托中,接受请求的对象将自己传给被委托者(代理人),使得被委托的操作可以引用接受请求的对象,举例而言:
上图中,Window类保存一个Rectangle类的实例变量rectangle来代理Rectangle类的特定操作,此时,如果我们访问了Window类实例对象window,并希望求其面积Area(),我们将该操作委托给其代理者rectangle,由它处理该操作。由于需要引用接受请求的对象,我们还需要将window实例对象通过传参方式传给rectangle,使其在Rectangle类中的操作可以引用window对象。
聚合:一个对象拥有另一个对象或对另一个对象负责,一般称一个对象包含另一个对象或者是另一个对象的一部分。聚合意味着聚合对象和其所有者具有相同的生命周期。
相识:一个对象仅仅知道另一个对象,又称关联或引用,是一种比聚合弱的关系,标识松散耦合。