《重构--改善既有代码的设计》--处理概括关系(11)

一、Pull Up Field(字段上移)

两个子类拥有相同的字段。将该字段移至超类。

二、Pull Up Method(函数上移)

有些函数,在各个子类中产生完全相同的结果。将该函数移至父类。

1、检查待提升函数,确定它们是完全一致的。

2、如果特提升函数名不同,修改与父类相同的函数名。

3、在父类新建一个函数,将待提升的函数代码复制到到新函数中。

4、编译。

5、移除子类中的函数。

6、编译、测试。

7、逐一移除子类中的函数,直到只剩下父类中的函数。

8、编译、测试。

重构后:

三、Pull Up Constructor Body(构造函数本体上移)

你在各个子类中拥有一些构造函数,它们的本体几乎完全一致。在父类中新建一个构造函数,并在子类构造函数中调用它。

1、在父类定义一个构造函数。

2、将子类共同代码搬移到父类中构造函数中。

3、将子类构造函数共同代码删除,改用父类中的构造函数。

4、编译、测试。

class Employee
    {
        protected string _name;
        protected string _id;

        public Employee(string name, string id)
        {
            _name = name;
            _id = id;
        }
    }

 

class Manager : Employee
    {
        private int _grade;
        public Manager(string name, string id, int grade)            
        {
            _name = name;
            _id = id;
            _grade = grade;
        }
    }

重构后:

class Manager : Employee
    {
        private int _grade;
        public Manager(string name, string id, int grade)    
            :base(name,id)
        {            
            _grade = grade;
        }
    }


四、Push Down Method(函数下移)

父类中的某个函数只与部分(而非全部)子类有关。将这个函数移到相关的那些子类去。

五、Push Down Field(字段下移)

父类中某个字段只被部分(而非全部)子类用到。将这个字段移到需要它的那些子类中。

六、Extract Subclass(提炼子类)

类中的某些特性只被某些(而非全部)实例用到。新建一个子类,将上面所说的那一部分特性移到子类中。

1、为源类定义一个新的子类。

2、为这个新的子类提供构造函数。

3、找出父类的构造函数,如果是需要子类的构造函数,请替换之。

4、逐一使用Push Down Method和Push Down Field将源类的特性移到子类。

5、编译、测试。

class JobItem
    {
        private int _unitPrice;
        private int _quantity;
        private bool _isLabor;
        private Employee _employee;

        public JobItem(int unitPrice, int quantity, bool isLabor, Employee employee)
        {
            _unitPrice = unitPrice;
            _quantity = quantity;
            _isLabor = isLabor;
            _employee = employee;
        }

        public int GetTotalPrice()
        {
            return GetUnitPrice() * _quantity;
        }

        public int GetUnitPrice()
        {
            return (_isLabor) ?
                _employee.GetRate() : _unitPrice;
        }

        public int Quantity
        {
            get { return _quantity; }
        }

        public Employee Employee
        {
            get { return _employee; }
        }
    }

 

class Employee
    {       
        protected int _rate;

        public Employee(int rate)
        {
            _rate = rate;   
        }

        public int GetRate()
        {
            return _rate;
        }
    }

 

class Program
    {
        static void Main(string[] args)
        {
            Employee kent = new Employee(3600);
            JobItem j1 = new JobItem(0, 5, true, kent); 
        }    
    }


创建一个子类,重构后:

class JobItem
    {
        private int _unitPrice;
        private int _quantity;
        private bool _isLabor;
        protected Employee _employee;

        protected JobItem(int unitPrice, int quantity, bool isLabor)
        {
            _unitPrice = unitPrice;
            _quantity = quantity;
            _isLabor = isLabor;         
        }

        public JobItem(int unitPrice, int quantity)
            : this(unitPrice, quantity, false)
        {
        }     

        public int GetTotalPrice()
        {
            return GetUnitPrice() * _quantity;
        }

        public virtual int GetUnitPrice()
        {
            return _unitPrice;
        }

        public int Quantity
        {
            get { return _quantity; }
        }

        protected virtual bool IsLabor()
        {
            return false;
        }
    }

 

class LaborItem:JobItem
    {
        public LaborItem(int unitPrice, int quantity, bool isLabor)
            : base(unitPrice, quantity, isLabor)
        {
        }

        public LaborItem(int quantity, Employee employee)
            : base(0, quantity, true)
        {
            _employee = employee;
        }

        public Employee Employee
        {
            get { return _employee; }
        }

        protected override bool IsLabor()
        {
            return true;
        }

        public override int GetUnitPrice()
        {
            return _employee.GetRate();
        }
    }

 

客户端:

class Program
    {
        static void Main(string[] args)
        {
            Employee kent = new Employee(3600);
            JobItem j1 = new LaborItem(10, 5, true);
            JobItem j2 = new JobItem(10, 15);
        }    
    }


 七、Extract Superclass(提炼超类)

两个类有相似特性。为这两个类建立一个父类,将相同特性移至父类。

1、建立一个抽象父类。

2、运用Pull Up Field,Pull Up Method,Pull Up Constructor Boday逐一将子类共同元素上移到父类。

3、编译、测试。

八、Extract Interface(提炼接口)

若干客户使用类接口中的同一子集,或者两个类的接口有部分相同。将相同的子集提炼到一个独立接口中。

1、新建一个接口。

2、在接口中声明待提炼类的共通操作。

3、让相关的类实现其接口。

4、调整客户端的类型声明,令其使用该接口。

 class Employee 
    {
        private int _rate;
        private bool _isSpecialSkill;

        Employee(int rate, bool isSpecialSkill)
        {
            _rate = rate;
            _isSpecialSkill = isSpecialSkill;
        }

        public int GetRate()
        {
            return _rate;
        }

        public bool HasSpecialSkill()
        {
            return _isSpecialSkill;
        }
    }

 

class TimeSheet
    {
        double Charge(Employee employee, int days)
        {
            int basic = employee.GetRate() * days;
            return (employee.HasSpecialSkill()) ? (basic * 1.05) : basic;         
        }
    }


重构后:

interface IBillable
    {
        int GetRate();
        bool HasSpecialSkill();
    }

 

class TimeSheet
    {
        double Charge(<span style="color:#ff0000;">IBillable </span>employee, int days)
        {
            int basic = employee.GetRate() * days;
            return (employee.HasSpecialSkill()) ? (basic * 1.05) : basic;         
        }
    }


九、Collapse Hierarchy(折叠继承体系)

父类与子类之间无太大区别,将它们合为一体。

1、选择你想移除的类:父类或子类。

2、使用Pull Up Field,Pull Up Method或Push Dwon Field,Push Down Method,把想移除的行为和属性搬移到另一个类中。

3、编译、测试。

4、调整原类的引用点,改为新类的引用。

5、移除源空类。

6、编译、测试。

十、Form Template Method(塑造模板函数)

你有一些子类,其中相应的函数以相同的顺序执行类的操作,但各个操作的细节上有所不同。将这些操作分别放进独立函数中,并保持它们都有相同的签名,于是原函数也就变得相同了。然后将原函数上移至父类。

1、在各个子类中分解目标函数,使分解后的各个函数不完全相同。

2、运用Pull Up Method将各个子类完全相同的函数上移父类。

3、对于那些完全不同的函数,实施Rename Method,使这些函数的签名完全相同。

4、编译、测试。

5、运用Pull Up Method将所有函数逐一上移到父类,并声明为抽象函数。

6、编译、测试。

7、移除子类中的原函数,编译、测试。

重构后:

十一、Replace Inheritance with Delegation(以委托取代继承)

某个子类只使用父类接口中的一部分,或是根本不需要继承而来的数据。在子类中新建一个字段用以保存父类,调整子类函数,令它改而委托父类,然后去掉两者之间的继承关系。

1、在子类型新建一个字段,引用父类的一个实例。

2、修改子类所有函数,让它们不使用父类,转而使用字段。

3、编译、测试。

4、去除继承关系。

5、编译、测试。

十二、Replace Delegation with Inheritance(以继承取代委托)

你在两个类之间使用委托关系,并经常为整个接口编写许多极简单的委托函数。让委托类继承受托类。

1、让委托端成为受托端的子类。

2、编译。

3、将受托字段设为该字段所处对象本身。

4、去掉简单的委托函数。

5、编译、测试。

6、把调用委托的代码改为对象本身。

7、移除受托字段。

 class Person
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public string GetLastName()
        {
            return _name.SubString(_name.LastIndexOf(' ') +1);
        }
    }

 

class Employee
    {
        Person _person = new Person();

        public override string ToString()
        {
            return "Emp:" + _person.GetLastName();
        }
    }

重构后:

class Employee : Person
    {
        public override string ToString()
        {
            return "Emp:" + GetLastName();
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值