目标和基本原则
类发生变化时,进行最少的修改
继承不变部分,封装变化部分
父类的修改将会影响到所有子类
尽量不动高层设计,而改动低层实现(提高了复用性)
我们能使用的工具
抽象类(abstract)及继承(extends) 接口(interface)及实现(implements) 多态
策略模式
问题提出
类需要添加新方法change(),且不同子类中该方法的实现不同
public class O { public void steady() { // steady body } // 原有方法 } public class O1 extends O {} public class O2 extends O {}
解决方案比较
1、传参条件分支
实现 父类中新增扩充方法change(),方法体根据参数决定唯一分支,分支对应不同子类方法实现
好处 易于实现
坏处 ①分支较多时方法体过大不易维护②change每次扩充都需要变动源类(高层设计)③O2子类继承了不需要的分支代码change1④传参错误时可能走向错误分支
public class O { // 原有方法 public void steady() { // steady body } // *扩充方法 public void change(String s) { if ("change0".equals(s)) { } else if("change1".equals(s)) { // change1 body } else ("change2".equals(s)) { // change2 body } } }
2、子类覆写扩充方法
实现 父类中新增扩充方法change(),方法体为空,由各子类覆写各自的change()方法
好处 ①由低层实现决定行为,减少了高层设计的改动,提高了高层设计的可复用性②各子类仅持有自己的代码实现,结构条理③复用性和维护性,公共部分可提出至父类change(),修改可对所有子类生效
坏处 ①改动使所有子类均拥有方法change(),包括不应该有此方法的子类②无需change()的子类均要覆写空方法体,造成了代码重复
public class O { public void steady() { // steady body } // 原有方法 public void change() { } // *扩充方法 } public class O1 extends O{ @Override public void change() { // change1 body } } public class O2 extends O implements Changeable { @Override public void change() {} // O2不需要change()方法 }
3、将方法抽象为接口
实现 仅将发生变化的方法从源类提出至接口,不变的部分子类仍继承源类
好处 拥有上述[2、继承覆写]的所有好处,且不会因变动而改变所有子类,还提供了灵活性:仅需要该方法的子类实现接口,不需要不实现接口
坏处 接口不能实现,失去[2、继承覆写]的好处③,使各子类实现的共同部分重复,且对共同部分的修改要依次修改所有子类
public interface Changeable { public void change(); } public class O1 extends O implements Changeable { @Override public void change() { // change1 body } } public class O2 extends O implements Changeable { @Override public void change() {} // O2不需要change()方法 }