• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Using command pattern with a pool of receivers

 
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
As I understand, to create a command, I first need to create a receiver and pass the receiver to the constructor of a concrete command. For instance,

....
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
....

This requires to instantiate an instance of a receiver. In this case, the multiplicity of the command to the recever is 1:1 Suppose I want to create a pool of only 5 receivers. Are there any side effects if I modify the pattern to retrieve a receiver from the pool in the execute() method.
For instance

public class ConcreteCommand implements Command{
Receiver receiver = null;
......
public void execute(){
receiver = ReceiverPool.getReceiver();
receiver.process();
...
}

}
 
ranger
Posts: 17347
11
Mac IntelliJ IDE Spring
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Why can't you do

receiver = ReceiverPool.getReceiver();

in the constructor of the Command.
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The only negative impact I can see is that the Command needs to know about (and therefore is coupled to) the pool.

Alternatively, you can implement the pool as a Proxy to the receivers - that is, the command calls a process method on the pool, which simply delegates to one of the actual receivers in the pool. That way the command can be used both with a single receiver and a pool of receivers, without knowing about it. Nifty, but also slightly more complex...
 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm not sure where receiver came from ... the pattern book or your own requirements? I often put commands into a queue and have a pool of executors (threads) pull them out of the queue and execute them. This ought to work if you can hook commands up to receivers right before running them instead of at command constructor time. Or maybe the executors are the receivers?
 
Joe Nguyen
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mark,

Why can't you do
receiver = ReceiverPool.getReceiver();
in the constructor of the Command.


This won't work because the receiver instance is now permanently bound to the command. The reason of using a pool is because I want to release the receiver back to the pool once it done with the execute() method.
 
Joe Nguyen
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The receiver is in the class structure of the command pattern. Your suggestion requires that all receivers to have the same interface.


Command cmd = queue.getNext();
cmd.execute( receiver );
-or-
cmd.execute( this );
 
Joe Nguyen
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ilja,
Are you suggest that the command is better coupled to a proxy instead of a pool?
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Joe Nguyen:
Ilja,
Are you suggest that the command is better coupled to a proxy instead of a pool?



No - in fact the proxy *would be* the pool, but the command wouldn't know about it.

The command pattern should only know about an interface that both the actual receivers and the Proxy implement!



Hope this helps...
 
Stan James
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ilja's solution is pretty cool. It gives each command to the next available receiver. If you execute them immediately you should be fine, but if they execute asynchronously you'd have to be sure two commands with the same receiver don't try to execute at the same time.

I had to go pull GoF to read up on receiver. I wouldn't take the requirement that the receiver is bound to the command at constructor time too seriously. In an editor there would be only one receiver, perhaps the document object, but with your pool of receivers a little more flexbility is allowed. You could pick the receiver from the pool at execute time. You could even make the receivers as threads in a pool that pull commands from a queue and execute them with a double-dispatch kinda thing as I hinted with "command.execute(this)".

I'm not sure why you objected that all receivers would have to have the same interface. Don't they already? They must have some common type that commands can act upon to make "new Command(receiver)" work.

Could you describe your context a bit? What creates commands and when? For example, does a user click a button or do hundreds of remote clients send messages? Do commands execute immediately or go through a queue? Do your receivers run on separate threads?
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Stan James:
Ilja's solution is pretty cool.



Thanks!

It gives each command to the next available receiver. If you execute them immediately you should be fine, but if they execute asynchronously you'd have to be sure two commands with the same receiver don't try to execute at the same time.



Yes - I silently assumed that getReceiverToUse() would only return receivers that aren't currently processing something. That begs the question what happens when there isn't one available - should it block, throw an exception, enlarge the pool...

Thanks for pointing this out!
 
Mark Spritzler
ranger
Posts: 17347
11
Mac IntelliJ IDE Spring
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Joe Nguyen:
Mark,

Why can't you do
receiver = ReceiverPool.getReceiver();
in the constructor of the Command.


This won't work because the receiver instance is now permanently bound to the command. The reason of using a pool is because I want to release the receiver back to the pool once it done with the execute() method.



OK, then why can't you do



Mark
 
Joe Nguyen
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks guys. It is indeed a much better solution.

Stan,
We have a home-grown messaging frame work in which user request is encapsulated in a command and then inserted into a queue. We have many different types of receivers that do not share a commond interface. We also have many pools of receivers.
When a queue is not empty, a thread from the thread pool will be retrieved to handle a command in the queue.
 
Stan James
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sounds like an interesting (!) environment. I won't waste your time by guessing around it any more since you have some thoughts that look like they'll work. Given my past habits, I'd probably make the command look for a receiver at execute time. Maybe each command would know the key to a map of pools that it could pull a receiver from. D'oh! There I went and did it again.
 
It's weird that we cook bacon and bake cookies. Eat this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic