Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

职责链模式中,对象使用和实现一个接口(一个或者更多方法)意欲松散耦合。一组实现这个接口的对象组成一个列表(或至少是一个树)。使用这个接口的对象从第一个实现对象开始进行请求。第一个实现对象会决定它自己是否进行任何行为并且是否将请求在列表(或树)中传递下去。有时候如果没有任何实现相应请求,则也要为此编写一个默认的实现。

例子

在这个例子中,脚本发送请求给lister对象,lister指向一个UnixLister对象。如果它不能处理请求,它会发送请求给WindowsLister。如果它也不能处理请求,它会发送请求给DefaultLister

Code Block
class UnixLister {
    private nextInLine
    UnixLister(next) { nextInLine = next }
    def listFiles(dir) {
        if (System.getProperty('os.name') == 'Linux')
            println "ls $dir".execute().text
        else
            nextInLine.listFiles(dir)        
    }
}

class WindowsLister {
    private nextInLine
    WindowsLister(next) { nextInLine = next }
    def listFiles(dir) {
        if (System.getProperty('os.name') == 'Windows XP')
            println "cmd.exe /c dir $dir".execute().text
        else
            nextInLine.listFiles(dir)        
    }
}

class DefaultLister {
    def listFiles(dir) {
        new File(dir).eachFile{ f -> println f }
    }
}

def lister = new UnixLister(new WindowsLister(new DefaultLister()))

lister.listFiles('Downloads')

输出应该是一个文件的列表(不同的操作系统上格式稍微有些不同)

这里是一个UML演示:

该模式的变形:

 

  • 为了静态的将实现归类,我们可以有一个显式的接口,例如,Lister。但是因为duck-typing所以是可选的。
  • 我们可以使用一个职责树而不是一个列表,例如,如果(animal.hasBackbone())则委托给VertebrateHandler否则委托给InvertebrateHandler
  • 我们可以一直在链上传递下去,即使我们已经处理了一个请求。
  • 我们可以决定何时不响应请求,何时不继续传递下去。
  • 我们可以用Groovy的元编程能力在链上传递未知的方法。