• 重构手法之处理概括关系【2】


    返回总目录

    本小节目录

    4Push Down Method(函数下移)

    概要

    基类中的某个函数只与部分(并非全部)子类有关。

    将这个函数移到相关的那些子类去。

    动机

    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
    {
    }

    小结

    面向对象三大特征(继承、封装、多态)很多时候可以帮助我们,但同时也可能会造成使用过度或者使用不当,所以如何把握好设计,这个就变得至关重要。在什么时候使用继承的方式,在什么时候使用组合和聚合,接口和继承类的选择等就成了我们的重点。

    5Push Down Field(字段下移)

    概要

    基类中的某个字段只被部分(并非全部)子类用到。

    将这个字段移到需要它的那些子类去。

    动机

    如果只有某些(而非全部)子类需要基类内的一个字段,就可以使用本项重构。

    范例

    如下代码所示,基类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
    {
    }

    小结

    此重构也是一个非常简单的重构,在很多时候我们都会不自觉的使用它。

    6Extract Subclass(提炼子类)

    概要

    类中的某些特性只被某些(而非全部)实例用到。

    新建一个子类,将上面所说的那一部分特性转移到子类中。

    动机

    使用本项重构的主要动机是:你发现类中的某些行为只被一部分实例用到,其他实例不需要它们。

    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……

  • 相关阅读:
    不怕上不了 Android developers
    不花钱的可靠性设计
    linux2.6 内核特性配置
    Linux动态库的编译与使用 转载
    多线程使用互斥锁的C范例
    TSLIB 分析
    Notepad++中文版下载 以及HEX显示
    C程序实现在lcd 上全屏写 blue 色 及获取fb信息
    pthread_cond_wait的spurious wakeup问题
    查看linux内存条数的命令与清理内存使用
  • 原文地址:https://www.cnblogs.com/liuyoung/p/7965966.html
Copyright © 2020-2023  润新知