Effective Java学习--第16条:复合优先于继承
来源:互联网 发布:python 函数 编辑:程序博客网 时间:2024/04/30 12:48
在系统分析设计这门课中某王就不停地强调一点,就是ISA(is a 原则)。都知道继承是面向对象的一大要素,但是哪里使用复合哪里使用继承,其实还是有讲究的。
可以简单的用ISA原则概括。有一个具备一定功能类,我们要对其功能进行拓展,到底是采用复合呢还是继承呢?当新类与旧类的关系是从属关系是,即cat is an animal,English book is a book,我们优先使用继承;当新类是旧类的组成部分之一时,即hand is a part of body,jiangsu is a part of China,我们优先使用复合。
理由如下:当我们要扩展一个类时,特别是一个别人写好的类,一个类库的类,我们往往关心的仅仅是单个api的功能,而不关心他的实现,但是存在的一个问题就是,同一个类的各个方法直接可能存在联系,可能一个方法的实现依赖于另一个方法,这就意味着,当我们调用一个我们想要操作的方法时,“继承”会隐式的调用另一个方法,这就可能存在问题。
经典的例子是Set中add()和addAll()的内在联系。
需求:新建一个集合类,维护一个addCount变量,记录,一共添加了多少次新值。分别用继承,复合实现。
先看继承:
MySet.java
package cczu.edu.test2;import java.util.Collection;import java.util.HashSet;public class MySet<E> extends HashSet<E>{ private int addCount = 0; public MySet() { } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; }}
Test
@Test public void test1(){ MySet<String> set = new MySet<String>(); List<String> list = new ArrayList<String>(); list.add("abc"); list.add("def"); list.add("ghi"); set.addAll(list); System.out.println(set.getAddCount()); //the ans is 6 }
因为,在hashSet的addAll()实现中,是循环调用add()方法的,所以导致3*2。当然你也可以重写addAll()方法,但是这样就失去了继承的意义。
使用复合:
ForwardingSet.java
package cczu.edu.test2;import java.util.Collection;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class ForwardingSet<E> implements Set<E> { private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } public ForwardingSet(){ this.s = new HashSet<E>(); } @Override public int size() { return s.size(); } @Override public boolean isEmpty() { return s.isEmpty(); } @Override public boolean contains(Object o) { return s.contains(o); } @Override public Iterator<E> iterator() { return s.iterator(); } @Override public Object[] toArray() { return s.toArray(); } @Override public <T> T[] toArray(T[] a) { return s.toArray(a); } @Override public boolean add(E e) { return s.add(e); } @Override public boolean remove(Object o) { return s.remove(o); } @Override public boolean containsAll(Collection<?> c) { return s.containsAll(c); } @Override public boolean addAll(Collection<? extends E> c) { // TODO Auto-generated method stub return false; } @Override public boolean retainAll(Collection<?> c) { return s.retainAll(c); } @Override public boolean removeAll(Collection<?> c) { return s.removeAll(c); } @Override public void clear() { s.clear(); }}
Myset2.java
package cczu.edu.test2;import java.util.Collection;public class MySet2<E> extends ForwardingSet<E>{ private int addCount = 0; @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; }}
Test
@Test public void test2(){ MySet2<String> set = new MySet2<String>(); List<String> list = new ArrayList<String>(); list.add("abc"); list.add("def"); list.add("ghi"); set.addAll(list); System.out.println(set.getAddCount()); //the ans is 3 }
增加一个ForwardingSet.java,作用仅仅就是实现转发。
回过头来看,复合可以将旧类完全地包裹起来,以至于我们不需要关注旧类的实现,同时达到可以调用旧类方法的效果,避免了旧类各个方法之间存在的联系,再加入旧类如果还有其他的权限问题,复合也可以隐藏缺陷。
自我总结:其实设计模式中例如代理模式,适配器模式,装饰器模式,和继承、复合都有些联系,以至于我都有一点混淆,毕竟,设计模式是死的,思想是活的。
- Effective Java学习--第16条:复合优先于继承
- Effective Java 第16条 : 复合优先于继承
- 《Effective java》读书记录-第16条-复合优先于继承
- 第16条:复合优先于继承
- 第16条:复合优先于继承
- 第16条:复合优先于继承
- Effective Java学习笔记:复合优先于继承
- Effective Java读书笔记-复合优先于继承
- effective java(16) 之复合优先于继承
- Effective Java 16:复合优先于继承 Favor composition over inheritance
- 第十六条:复合优先于继承
- Java学习笔记13:复合优先于继承
- Java:Effective Java 学习笔记(第49条:基本类型优先于装箱基本类型)
- Effective Java学习--第22条:接口优先于抽象类
- 复合优先于继承
- 复合优先于继承
- 复合优先于继承。
- Java程序设计之-复合优先于继承
- 集成p6spy到spring中
- Torch7深度学习教程(三)
- STM32串口设定流程总结
- 批处理命令forfiles语法的实例详解
- 【shell】shell脚本在大文件日志中按照时间段快速搜索日志
- Effective Java学习--第16条:复合优先于继承
- JS-charts
- Perl打印输出二进制文件
- 数据结构实验之链表五:单链表的拆分
- Path类介绍
- Beacon技术是什么?
- Maven中的DependencyManagement和Dependencies
- Spring的接口注入
- Java 设计模式(九) Strategy(策略)模式及Spring引申