Intent Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
Problem There is a potentially variable number of "handler" objects and a stream of requests that must be handled. Need to efficiently process the requests without hard-wiring handler relationships and precedence, or request-to-handler mappings.
Structure  Steps are as follow:
1. Base class maintains a "next" pointer 2. Each "link" does its part to handle (and/or pass on) the request 3. Client "launches and leaves" each request with the chain 4. The current bid and bidder are maintained in chain static members 5. The last link in the chain assigns the job to the low bidder
-
- /**
- * This class is the abstract class from which all elements in the
- * chain inherit.
- */
- public abstract class Handler
- {
- //HAS:
- //Each element in the chain has a title (such as secretary), a
- //superior (such as Governer), and a beurocratic response to use
- //in responding to a letter that it handles.
- Handler superior = null;
- String title;
- //note the irony of the static nature of the beurocratic response.
- static final String beurocraticResponse = "Thank you for your letter. It's not our fault. Send us more money. Sincerely, Governer Taft.";
-
- //There is no CONSTRUCTOR becuase the class is abstract.
-
- //METHODS:
- //This method changes from chain element to chain element
- //because each element uses different criteria to evaluate
- //whether the letter is handleable and there is no method body
- //filled in in the abstract class.
- abstract boolean canHandle(Letter kvetch);
-
- //This method remains constant for all chain elements, and so can
- //be written here once and for all.
- public Letter handleLetter(Letter kvetch)
- {
- //if the element in the chain can handle the letter,
- if(this.canHandle(kvetch))
- {
- //Send a reply.
- return new Letter(kvetch.getSender(), "Governor Taft", beurocraticResponse, kvetch.getSubject());
- }
-
- //otherwise, it becomes my bosses problem.
- else if(superior != null)
- {
- return superior.handleLetter(kvetch);
- }
- //The Governor doesn't have a boss whose problem it can
- //become, so just in case, we account for this exception.
- throw new java.lang.RuntimeException("Invalid Recipient -- No one can handle this problem.");
- }
- }
-
- public class Letter extends Object
- {
-
- //HAS:
- //The letter has four parts (four Strings): A string to represent
- //the recipient, sender, content of the letter (text), and subject
- //of the letter. Each object in the chain uses the subejct string
- //to determine whether it can handle the letter.
- String recipient = new String("");
- String sender = new String("");
- String text = new String("");
- String subject = new String("");
-
- //CONSTRUCTOR
- public Letter(String isTo, String isFrom, String contents, String topic)
- {
- //Always a good idea to call the super's constructor.
- super();
- //initializations for the letter happen in its constructor.
- setRecipient(isTo);
- setSender(isFrom);
- setText(contents);
- setSubject(topic);
- }
-
- //Accessor METHODS for each of the four strings.
- public String getRecipient()
- {
- return this.recipient;
- }
-
- public String getSender()
- {
- return this.sender;
- }
-
- public String getText()
- {
- return this.text;
- }
-
- public String getSubject()
- {
- return this.subject;
- }
-
- private void setRecipient(String isTo)
- {
- this.recipient = isTo;
- }
-
- private void setSender(String isFrom)
- {
- this.sender = isFrom;
- }
-
- private void setText(String contents)
- {
- this.text = contents;
- }
-
- private void setSubject(String topic)
- {
- this.subject = topic;
- }
-
- //Overriden toString METHOD so that we can use letters as the selected items in the combobox.
- public String toString()
- {
- return this.getSubject();
- }
- }
-
- public class Governer extends Handler
- {
- //CONSTRUCTOR for Governor is different from all the other
- //handlers because it doesn't have a "boss" and thus its superior is
- //set to null.
- public Governer()
- {
- super();
- this.superior= null;
- this.title = "Governer";
- }
-
- //METHOD
- public boolean canHandle(Letter kvetch)
- {
- //The Governer only handles donations.
- if(kvetch.getSubject().equalsIgnoreCase("Donation")) return true;
- else return false;
- }
-
- }
-
- public class Secretary extends Handler
- {
- //CONSTRUCTOR
- public Secretary(Handler boss)
- {
- super();
- this.superior = boss;
- this.title = "Secretary";
- }
-
- //METHOD
- public boolean canHandle(Letter kvetch)
- {
- //The Secretary only handles accusations.
- if(kvetch.getSubject().equalsIgnoreCase("Accusation")) return true;
- else return false;
- }
- }
-
-
-
- //The concrete extender of HANDLER, the LACKEY class:
-
- public class Lackie extends Handler
- {
-
- //CONSTRUCTOR
- public Lackie(Handler boss)
- {
- super();
- this.superior = boss;
- this.title = "Lackie";
- }
-
- //METHOD
- public boolean canHandle(Letter kvetch)
- {
- //The Lackey only handles inquiries.
- if(kvetch.getSubject().equalsIgnoreCase("Inquiry")) return true;
- else return false;
- }
- }
-
- public class MailClerk extends Handler
- {
-
- //CONSTRCUTOR
- public MailClerk(Handler boss)
- {
- super();
- this.superior = boss;
- this.title = "Mail Clerk";
- }
-
- //METHOD
- public boolean canHandle(Letter kvetch)
- {
- //The Mail Clerk only handles criticisms.
- if(kvetch.getSubject().equalsIgnoreCase("Criticism")) return true;
- else return false;
- }
-
- }
-
- public class ChainDemo2 {
- public static void main(String[] args) {
- //Instantiate the chain IN THIS ORDER!!!
- //Otherwise, they don't have bosses to use in their constructors.
- Governer taft = new Governer();
- Secretary marcia = new Secretary(taft);
- Lackie joe = new Lackie(marcia);
- MailClerk annie = new MailClerk(joe);
- }
- }
When to use This pattern deals with the relationship between a set of objects and a request. You apply this pattern when more than one object can handle a request. The first object in the chain gets the request and either resolves it or moves it along to the next object in the chain, until one can handle it. The original requesting object doesn't know which object will handle its request. The object that ultimately handles the request it said to be and implicit receiver. Restaurants are set up this way; a customer typically doesn't send a request directly to a chef and isn't usually acquainted with the chef the request is going to do. Instead, the customer gives and order to a server, the server gets it to the chef, who might fulfils the order or pass it along to an assistant chef.
|