开发者

Would this still be considered a Chain-of-Responsiblity pattern?

I have been using a design pattern for quite some time and have been calling/referring to it as a "Chain-of-Responsibility pattern" but now I realise there are differences, and it may not be appropriate to do so. So my question is 1, "is the following an instance of this pattern, or should it be called something else?", and 2, "is there any reason I should prefer the traditional way?".

I often use the following pattern when developing software. I have an interface that defines a functor, something like this.

interface FooBar{
    boolean isFooBa开发者_StackOverflowr( Object o );
}

These are usually search, filtering, or processing classes; usually something like Comparator. The implementation method is usually functional (i.e. side-effect free). Eventually, I find myself creating an implementation of the interface that looks like:

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;
    }
}

Its not always booleans either -I've used this pattern with mutable objects as well- but there is always a short-circuiting condition (e.g. returns true, the String is empty String, a flag gets set etc).

Until now I have generally calling this a "Chain of Responsibility" pattern, considering the issue of inheriting from a base class to be an implementation detail. However, today I have realised an important difference: the objects along the chain cannot interrupt the rest of chain. There is no way for an implementation to say "this is false, and I can guarantee it will be false for any condition" (nb: short-circuits only on true ).

So, should this be called something other than a chain-of-responsibility pattern? Are there any concerns or issues I should consider when using this approach over the traditional having the instances pass the message along.


I wouldn't call this chain of Chain of Responsibility.

In Chain of Responsibility, the "short-circuit" is roughly "I can handle this, so the next guy in the chain doesn't have to" rather than being a return value of any kind. It's normal for each object in the chain to know who is next in the chain and to pass control to that next object as necessary. They normally do something rather than returning a value.

The example you've presented it is perfectly reasonable, though I'm not sure it's a named pattern. I'm not too clear right now on the other variants you describe.


What you have is a chain-of-responsibility, but you can make a 'pure' chain of responsibility by adding a few small changes.

You can create an enum that will represent the 3 different results that you are expecting from this function.

 public enum Validity{
     Invalid,
     Indeterminate,
     Valid
 }

You can change the interface to be chain-able like so:

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

Most of your FooBars would then have to implement a method like this:

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

Then you can change your chain to check for either of the definite answers.

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;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜