第11章 处理概括关系

字段上移(Pull Up Field)

1.概念:两个子类拥有相同的字段,将字段移至超类。

2.动机:子类如果是分别开发的,可能具有重复的特性,特别是字段容易重复,如果确认了字段的使用方式很相似,就可以把它们归到超类去。

 

函数上移(Pull Up Method)

1.概念:有些函数,在各个子类中产生完全相同的结果,则将函数移至超类。

2.动机:一种情况是类似字段上移的动机,还有一种情况是子类的函数覆写了超类的函数,却仍然做着相同的工作,此时也需要将函数上移。

3.做法:注意因为子类中的函数并不相同,我们必须在超类中声明它们的抽象函数。

 

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

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

2.动机:如果你看见各个子类中的函数有共同的行为,首先应该想到将它们的共同行为提炼到一个独立函数中,然后将这个类提升为超类。对于构造函数来说,子类共同的行为就是“对象的构建”。

3.做法:

(1)在超类中定义一个构造函数。

(2)将子类构造函数中的共同代码搬移到超类构造函数中。

(3)将子类构造函数共同代码删掉,改而调用新建的超类构造函数。

(4)编译,测试。

//超类
class
Emploee { protected Employee(String name, String id) { this.name = name; this.id = id; } }
//子类中调用
public Manager(String name, String id, int grade) {
    super(name, id);
    this.grade = grade;
}

 

函数下移(Push Down Method)

1.概念:超类中的某个函数只与部分(而非全部)子类有关,则将这个函数移到相关的那些子类中去。

 

字段下移(Push Down Field)

1.概念:超类中的某个字段只被部分(而非全部)子类用到,则将这个字段移到需要它的那些子类去。

 

提炼子类(Extract Subclass)

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

提炼超类(Extract Superclass)

1.概念:

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

 

提炼接口(Extract Interface)

1.概念:

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

2.动机;

类彼此之间有很多种互用的方式,“使用一个类”通常意味着用到该类的所有责任区。但如果一组客户只使用到类责任区中的一个特定子集,或者这个类需要与所有协助处理某些特定请求的类合作,面对这两种情况,将这部分用到的职责分离出来就很有意义。这样使用法更清晰,责任划分更清晰。

 

折叠继承体系(Collapse Hierarchy)

1.概念:

超类和子类之间无太大区别,则将它们合为一体。

 

塑造模板函数(Form TemPlate Method)

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

(略,待细看)

 

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

1.概念:

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

(委托:在A类中实例化B类对象,并在A类方法中通过实例出的B类对象返回B类的东西)

2.动机:

继承虽好,但并不一定是你想要的。当一开始继承了一个类,然后发现超类中很多操作并不真正适用于子类,则改用委托取代继承。

3.做法:

滥用继承的一个典型的范例就是让stack类继承Vector类,其中客户端Stack只需要做4件事,push(), pop(), 还有从vector继承来的size(), isEmpty():

//原式
class
MyStack extends Vector { public void push(Object element) { insertElement(element, 0); } public Object pop() { Object result = firstElement(); removeElementAt(0); return result; } }

(1)在子类中新建一个字段,使其引用超类的一个实例,并将它们初始化为this。

(2)修改子类内的所有函数,让它们不再使用超类,转而使用上述的受托字段,每次修改后,编译并测试。

class Mystack extends Vector {
    private Vector vector = this;

    public void push(Object element) {
        vector.insertElementAt(element, 0);
    }

    public Object pop() {
        Object result = vector.firstElement();
        vector.removeElementAt(0);
        return result;
    }
}

(3)去除两个类之间的继承关系,新建一个受托类的对象赋给受托字段。

(4)针对客户端所用的每一个超类函数,为它添加一个简单的委托函数。

class Mystack {
    private Vector vector = new Vector();

    //添加委托函数
    public int size() {
        return vector.size();
    }

    public boolean isEmpty() {
        return vector.isEmpty();
    }
}

 

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

1.概念:

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

2.动机:

与“以委托取代继承”相反,如果你发现自己需要使用受托类中所有函数,并花了很大力气编写所有极简的委托函数时,用此重构。

posted @ 2020-08-28 14:53  pmingup9012  阅读(147)  评论(0编辑  收藏  举报