7.1 传递式方法

当相邻的层有相似的抽象时,问题经常以传递式方法(pass-through method)的形式表现出来。传递式方法是除了调用另一个方法之外几乎没有什么作用的方法,其签名与调用方法的签名相似或相同。例如,一个实现GUI文本编辑器的学生项目包含一个几乎完全由传递式方法组成的类。下面是该类的一个摘录:

public class TextDocument ... {
    private TextArea textArea; 
    private TextDocumentListener listener; 
    ...
    public Character getLastTypedCharacter() {
        return textArea.getLastTypedCharacter(); 
    } 
    public int getCursorOffset() {
        return textArea.getCursorOffset(); 
    } 
    public void insertString(String textToInsert, int offset) {
        textArea.insertString(textToInsert, offset); 
    } 
    public void willInsertString(String stringToInsert, int offset) {
        if (listener != null) {
            listener.willInsertString(this, stringToInsert, offset);
        } 
    } 
    ...
}

在该类的15个公共方法中,有13个是传递式方法。

危险信号:传递式方法

传递式方法使类变浅:它们增加了类的接口复杂性,从而增加了复杂性,但它们并没有增加系统的总功能。在上面的四个方法中,只有最后一个有一点微不足道的功能:该方法检查了一个变量的有效性。传递式方法还在类之间产生了依赖:如果 TextAreainsertString方法的签名发生更改,则 TextDocument 中的 insertString 方法必须更改以匹配。

传递式方法表明类之间的职责划分存在混乱。在上面的例子中,TextDocument类提供了一个insertString方法,但插入文本的功能完全在TextArea中实现。这通常是个坏主意:一个功能的接口应该在实现该功能的同一个类中。当你看到从一个类到另一个类的传递式方法时,考虑一下这两个类,并问自己:“这些类到底分别负责哪些功能和抽象?”你可能会注意到,这两个类之间存在职责重叠的情况。

解决办法是重构这些类,使每个类都有一套独特且连贯的职责。图7.1展示了几种实现这一目的的方法。一种方法,如图7.1(b)所示,是将较低级别的类直接暴露给较高级别的类的调用者,从后者中移除对该功能的所有职责。另一种方法是在类之间重新分配功能,如图7.1(c)所示。最后,如果这些类不能被分离,最好的解决办法可能是将它们合并,如图7.1(d)所示。

图7.1: 传递式方法。在(a)中,C1类包含三个传递式方法,它们除了调用C2中具有相同签名的方法外,什么都不做(每个符号代表一个特定的方法签名)。可以通过让C1的调用者直接调用C2(如(b)),通过在C1和C2之间重新分配功能以避免类之间的调用(如(c)),或者通过合并类来消除这些传递式方法。

在上面的示例中,有三个职责交织在一起的类:TextDocumentTextAreaTextDocumentListener。 学生通过在类之间移动方法并将三个类合并为两个来消除传递式方法,这两个类的职责更加明确。

Last updated