这还会被视为责任链模式吗?

时间:2011-06-28 15:56:04

标签: oop design-patterns chain-of-responsibility

我一直在使用设计模式很长一段时间,并且一直在调用/称之为“Chain-of-Responsibility pattern”,但现在我意识到存在差异,这可能不合适。所以我的问题是1,“以下是这种模式的一个实例,还是应该被称为其他东西?”和2,“有什么理由我更喜欢传统方式吗?”。

我在开发软件时经常使用以下模式。我有一个定义functor的界面,就像这样。

interface FooBar{
    boolean isFooBar( Object o );
}

这些通常是搜索,过滤或处理类;通常类似于Comparator。实现方法通常是功能性的(即无副作用)。最后,我发现自己创建了一个接口的实现,如下所示:

class FooBarChain implements FooBar{
    FooBar[] foobars;

    FooBarChain( FooBar... fubars ){
         foobars = fubars;
    }

    boolean isFooBar( Object o ){
         for( FooBar f : foobars )
             if(  f.isFooBar( o )  )
                 return true;

         return false;
    }
}

它也不总是布尔 - 我已经将这种模式与可变对象一起使用 - 但总是存在短路条件(例如返回true,String为空String,标志设置等)。

到目前为止,我一般将此称为“责任链”模式,考虑从基类继承为实现细节的问题。但是,今天我已经意识到一个重要的区别:链条上的物体不能打断链条的其余部分。实现没有办法说“这是错误的,我可以保证它对于任何条件都是假的”(nb:仅在true上短路)。

那么,这应该被称为责任链模式以外的东西吗?使用这种方法时,我应该考虑任何问题或问题,而不是传统的实例传递信息。

2 个答案:

答案 0 :(得分:2)

我不会将此链称为责任链。

在责任链中,“短路”大致是“我可以处理这个,所以链中的下一个人不必”而不是任何类型的返回值。链中的每个对象通常知道链中的下一个是谁,并在必要时将控制传递给下一个对象。他们通常做某事而不是返回一个值。

你提出它的例子是完全合理的,虽然我不确定它是一个命名模式。我现在对你描述的其他变种我不太清楚。

答案 1 :(得分:1)

你所拥有的是一个责任链,但你可以通过添加一些小的变化来建立一个“纯粹的”责任链。

您可以创建一个枚举,它将代表您希望从此功能获得的3种不同结果。

 public enum Validity{
     Invalid,
     Indeterminate,
     Valid
 }

您可以将界面更改为可链式,如下所示:

 public interface ChainFooBar{
     public boolean isFooBar(Object o);
     public Validity checkFooBar(Object o);
 }

您的大多数FooBar必须实现这样的方法:

public abstract class AbstractFooBar implements FooBar{
    public Validity checkFooBar(Object o){
        return this.isFooBar(o) ? Validity.Valid : Validity.Indeterminate;
    }
}

然后你可以改变你的链以检查任何明确的答案。

public class FooBarChain implements FooBar{
    private FooBar[] fooBars;

    public FooBarChain(FooBar... fooBars){
        this.fooBars = fooBars;
    }

    public Validity isFooBar(Object o){
        for(FooBar fooBar : this.fooBars){
            Validity validity = fooBar.checkFooBar(o);
            if(validity != Validity.Indeterminate){
                return validity == Validity.Valid;
            }
        }
        return false;
    }
}