复合优于继承
这句话是Effective Java中非常经典的一句话。继承就是子类和父类之间的耦合,子类依赖了父类的实现,打破了封装性。
很多时候写代码使用继承是为了把Common的方法都放到基类中
public class BaseClass{
protected void method1() {
}
protected void method2() {
}
}
public class ClassA extends BaseClass {
public void method3() {
super.method()1;
......
}
}
这种情况下是最没有必要的继承关系,应该将BaseClass变成一个一个Service,ClassA里面的方法调用Service内的方法,这样就弱化了依赖关系
Effective Java中举了一个非常好的例子。一个人想要自己写一个Set类,统计Set里面元素的个数,用了继承的方式
public class MySet<T> extents HashSet<T> {
private int totalCount;
@Override
public boolean add(T element) {
this.totalCount +=1;
return super.add(element);
}
@Override
public boolean addAll(Collection<T> elements) {
this.totalCount += elements.size();
return super().addAll(elements);
}
}
这个时候如果调用addAll方法,添加3个元素,最后totalCount会是6。因为HashSet的addAll循环调用了add方法。
而如果是组合关系就不会有这个问题,将HashSet实例作为MySet的成员变量就好了。
可以使用继承的情形
1. 模板方法
这是一种设计模式,使用下来在一些小范围中还是比较方便的
public abstract class BaseClass {
public void do() {
step1();
step2();
step3();
}
private void step1() {
}
private void step3() {
}
protected void abstract step2();
}
public class ClassA extends BaseClass{
@Override
public void step2() {
}
}
在实际开发中,因为继承的引用也有负面影响。比如有一次我需要在中间再加一步,有些子类需要实现,有些不需要,为了减少影响我只能让新加的步骤不是抽象方法,谁要用它就在子类中覆盖。一个还好,多个这种方法,继承结构就会越来越乱。
2. 为了继承而设计的类
今天刚刚碰到的一个例子,系统中所有的DB Entity都会有的字段是oid, version, create_by, last_update_by等等。那对应的,Entity对应的Vo就可以是一个基类,里面包含了所有common的字段,不用的vo就继承这个类,扩展自己特有的字段
3.真实存在的继承关系
比如系统中的地理信息。有行政区划、国家、省、市、区等。在真实中,国家、省、市等就是包含在行政区划下面的,这时候就可以是继承关系,他们都有一些共同的动作,比如告诉外部我是属于哪个洲的行政区划。
最后结论其实还是,能不用继承就不要用继承
网友评论