简体   繁体   中英

Chain of responsibility - handling more than one request

Right, this one might be a bit hard for me to explain since I am new to this.

I was given a task to use Chain of Responsibility to solve one of the problems. I had no problem with understanding it and implementing until I found out I have to make sure that my chain is capable of handling more than one request at once.

The chain essentially should work like that: In the whole chain, there are two or more pieces that are capable of handling the same problem. Handling one problem takes a whole minute. If one of the handlers is busy, the request goes straight to the next one (skips the handler that is busy completely).

So my question is: How do I send multiple requests one after another?

First off, that is a specialised implementation of chain of responsibility. Don't think that all chains of responsibility do things like this, because they don't.

That being said, if you want to run the second task while the first is still running then the main thing you need to ensure is that you don't block your caller ("main") thread. I suppose the slow element would need to shift the work onto some other thread and have a flag to denote it is busy doing something.

Here's a quick code sketch

interface Link {
    void handle(int i);
}

class SlowLink implements Link {
    private final AtomicBoolean isBusy = new AtomicBoolean(false);
    private final Link next;

    SlowLink(Link next) { this.next = next; }

    @Override
    public void handle(int i) {
        if (isBusy.compareAndSet(false, true)) {
            new Thread(() -> handleAsync(i)).start();
        }
        else {
            next.handle(i);
        }
    }

    private void handleAsync(int i) {
        try {
            Thread.sleep(3000);
            System.out.println("slow " + i);
            isBusy.set(false);
        }
        catch (InterruptedException e) {}
    }
}

class QuickLink implements Link {
    @Override
    public void handle(int i) {
        System.out.println("quick " + i);
    }
}

class Scratch {
    public static void main(String[] args) throws InterruptedException {
        Link chain = new SlowLink(new QuickLink());
        chain.handle(5);
        Thread.sleep(1000);
        chain.handle(2);
    }
}

As Michael has mentioned yours is a special implementation of COR ( Chain of Responsibility ).

If your requirement is just an asynchronous multi threaded code , then COR is not a candidate pattern to be used. Instead use Customized Singleton with capability of providing next available instance from a pool of 'n' instances.

If you have requirement of handling multiple types of request, with some type of requests being handled in asynchronous way, then using COR will help.

If we see the structure of COR pattern, it contains a chain formed by links of type Handler with method handleRequest() . Each concrete Handler specializes itself in handling one type of request by implementing handleRequest() something like following

if (canHandle){
    handleIt();
} else if (hasNextHandler()){
    passItToNextHandler();
} else {
    // complete chain is unable to handle it. So leave it may be log it
}

Now as you have two (or more) handler instances of same Concrete type in a chain, this looks like hack for violation (though it will work).

I would rather suggest keeping COR clean by linking single instance of each type of concrete handler in a chain. The handler where you need multiple instances in asynchronous way, delegate this multi threading task to an object pooling from handleRequest(). May be as a customized Singleton which handles 'n' instances instead of single.

This will separate two concerns namely COR and Object pooling. Both can be maintained independently without requirement of any Hack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM