返回总目录
本小节目录
基类中的某个函数只与部分(并非全部)子类有关。
将这个函数移到相关的那些子类去。
Push Down Method与Pull Up Method恰恰相反。当我有必要把某些行为从基类中移至特定的子类时,就使用Push Down Method,它通常也只在这种时候有用。使用Extract Subclass之后可能会需要它。
如下代码所示,Animal类中的方法Bark()只有在其子类Dog中使用,所以最好的方案就是把这个方法移到子类Dog中。
public class Animal { public void Bark() { // code to bark } } public class Dog : Animal { } public class Cat : Animal { }
重构后的代码如下,同时在父类Animal中如果没有其他的字段或者公用方法的话,可以考虑把Bark()方法做成一个接口,从而去掉Animal类。
public class Animal { } public class Dog : Animal { public void Bark() { // code to bark } } public class Cat : Animal { }
面向对象三大特征(继承、封装、多态)很多时候可以帮助我们,但同时也可能会造成使用过度或者使用不当,所以如何把握好设计,这个就变得至关重要。在什么时候使用继承的方式,在什么时候使用组合和聚合,接口和继承类的选择等就成了我们的重点。
基类中的某个字段只被部分(并非全部)子类用到。
将这个字段移到需要它的那些子类去。
如果只有某些(而非全部)子类需要基类内的一个字段,就可以使用本项重构。
如下代码所示,基类Task类中的_resolution字段只会在子类BugTask中用到,所以就考虑把它放到BugTask类中。
public class Task { protected string _resolution; } public class BugTask : Task { } public class FeatureTask : Task { }
重构后的代码如下所示,这样做的好处可以简化基类,同时让其他没有使用它的子类也变得更加简单,如果这样的字段比较多的话,使用此重构也能节约一部分内存。
public class Task { } public class BugTask : Task { protected string _resolution; } public class FeatureTask : Task { }
此重构也是一个非常简单的重构,在很多时候我们都会不自觉的使用它。
类中的某些特性只被某些(而非全部)实例用到。
新建一个子类,将上面所说的那一部分特性转移到子类中。
使用本项重构的主要动机是:你发现类中的某些行为只被一部分实例用到,其他实例不需要它们。
Extract Class是Extract Subclass之外的另一种选择,两者之间的抉择其实就是委托和继承之间的抉择。Extract Subclass通常更容易进行,但它也有限制:一旦对象创建完成,你无法再改变与类型相关的行为。但如果使用Extract Class,你只需插入另一个组件就可以改变对象的行为。此外,子类只能用以表现一组变化。如果你希望一个类以几种不同的方式变化,就必须使用委托。
当你的基类中存在一些方法不是所有的子类都需要访问,你想将它们调整到子类中时,这个重构会变得很有用了。如下代码所示,我们需要一个 Registration类用来处理学生选课的信息。但是当Registration类开始工作后,我们意识到我们会在两种不同的上下文中使用Registration类,NonRegistrationAction和Notes只有在我们处理未注册情况下才用到。
public class Registration { public NonRegistrationAction Action { get; set; } public decimal RegistrationTotal { get; set; } public string Notes { get; set; } public string Description { get; set; } public DateTime RegistrationDate { get; set; } }
重构后的代码如下所示,这样也满足面向对象五大原则之一的单一职责。同时也让类的结构变得更加清晰,增强了可维护性。
public class Registration { public decimal RegistrationTotal { get; set; } public string Description { get; set; } public DateTime RegistrationDate { get; set; } } public class NonRegistration : Registration { public NonRegistrationAction Action { get; set; } public string Notes { get; set; } }
这个重构方法经常用来规范类的职责,和之前的一些重构方法也有些类似。
To Be Continued……