Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Applied Java™ Patterns - Stephen Stelting, Olav Maassen.pdf
Скачиваний:
202
Добавлен:
24.05.2014
Размер:
2.84 Mб
Скачать

Forward to default handler – More complex than the base pattern, this approach uses a default event handler. Any message not explicitly handled at the component level, or forwarded to some other handler, will be sent to the default handler.

Ignore by default – Any message that is not explicitly handled or forwarded is discarded. If the classes in the chain produce events that are not used in the application, this can be an acceptable way to reduce chatter. However, you must be careful in this approach to avoid inadvertently discarding messages that the system should handle.

Related Patterns

Related patterns include the Composite (page 157). Chain of Responsibility is often used with the Composite pattern. When both are used together, the Composite pattern provides support for a tree-based structure and basic message propagation, and the Chain of Responsibility provides rules for how some of the messages are propagated.

In addition, Composite tends to send messages “down” the tree (from the root to the branches) while Chain of Responsibility usually sends messages “up” the tree (from branches to the root).

Example

Note:

For a full working example of this code example, with additional supporting classes and/or a RunPattern class, see “ Chain of Responsibility ” on page 366 of the “ Full Code Examples ” appendix.

The PIM can act as a project manager as well as a contact manager. This code example shows how to use the Chain of Responsibility pattern to retrieve information from within a project hierarchy.

The ProjectItem interface defines common methods for anything that can be part of a project.

Example 2.1 ProjectItem.java

1.import java.io.Serializable;

2.import java.util.ArrayList;

3.public interface ProjectItem extends Serializable{

4.public static final String EOL_STRING = System.getProperty("line.separator");

5.public ProjectItem getParent();

6.public Contact getOwner();

7.public String getDetails();

8.public ArrayList getProjectItems();

9.}

The interface defines the methods getParent, getOwner, getDetails, and getProjectItems. Two classes implement ProjectItem in this example — Project and Task. The Project class is the base of a project, so its getParent method returns null. The getOwner and getDetails methods return the overall owner and details for the project, and the getProjectItems method returns all of the project’s immediate children.

Example 2.2 Project.java

1.import java.util.ArrayList;

2.public class Project implements ProjectItem{

3.private String name;

4.private Contact owner;

5.private String details;

6.private ArrayList projectItems = new ArrayList();

8.public Project(){ }

9.public Project(String newName, String newDetails, Contact newOwner){

10.name = newName;

11.owner = newOwner;

12.details = newDetails;

13.}

14.

15.public String getName(){ return name; }

16.public String getDetails(){ return details; }

17.public Contact getOwner(){ return owner; }

18.public ProjectItem getParent(){ return null; }

38

19. public ArrayList getProjectItems(){ return projectItems; }

20.

21.public void setName(String newName){ name = newName; }

22.public void setOwner(Contact newOwner){ owner = newOwner; }

23.public void setDetails(String newDetails){ details = newDetails; }

25.public void addProjectItem(ProjectItem element){

26.if (!projectItems.contains(element)){

27. projectItems.add(element);

28.}

29.}

31.public void removeProjectItem(ProjectItem element){

32.projectItems.remove(element);

33.}

34.

35.public String toString(){

36.return name;

37.}

38.}

The Task class represents some job associated with the project. Like Project, Task can keep a collection of subtasks, and its getProjectItems method will return these objects. For Task, the getParent method returns the parent, which will be another Task for the Project.

Example 2.3 Task.java

1.import java.util.ArrayList;

2.import java.util.ListIterator;

3.public class Task implements ProjectItem{

4.private String name;

5.private ArrayList projectItems = new ArrayList();

6.private Contact owner;

7.private String details;

8.private ProjectItem parent;

9.private boolean primaryTask;

10.

11.public Task(ProjectItem newParent){

12.this(newParent, "", "", null, false);

13.}

14.public Task(ProjectItem newParent, String newName,

15.String newDetails, Contact newOwner, boolean newPrimaryTask){

16.

parent = newParent;

17.

name = newName;

18.

owner = newOwner;

19.

details = newDetails;

20.

primaryTask = newPrimaryTask;

21.

}

22.

 

23.public Contact getOwner(){

24.if (owner == null){

25. return parent.getOwner();

26.}

27.else{

28.

return owner;

29.}

30.}

32.public String getDetails(){

33.if (primaryTask){

34.

return details;

35.}

36.else{

37. return parent.getDetails() + EOL_STRING + "\t" + details;

38.}

39.}

41.public String getName(){ return name; }

42.public ArrayList getProjectItems(){ return projectItems; }

43.public ProjectItem getParent(){ return parent; }

44.public boolean isPrimaryTask(){ return primaryTask; }

45.

46.public void setName(String newName){ name = newName; }

47.public void setOwner(Contact newOwner){ owner = newOwner; }

48.public void setParent(ProjectItem newParent){ parent = newParent; }

49.public void setPrimaryTask(boolean newPrimaryTask){ primaryTask = newPrimaryTask; }

50.public void setDetails(String newDetails){ details = newDetails; }

39

51.

52.public void addProjectItem(ProjectItem element){

53.if (!projectItems.contains(element)){

54. projectItems.add(element);

55.}

56.}

58.public void removeProjectItem(ProjectItem element){

59.projectItems.remove(element);

60.}

61.

62.public String toString(){

63.return name;

64.}

65.}

The Chain of Responsibility behavior is manifested in the getOwner and getDetails methods of Task. For getOwner, a Task will either return its internally referenced owner (if non-null), or that of its parent. If the parent was a Task and its owner was null as well, the method call is passed on to the next parent until it eventually encounters a non-null owner or it reaches the Project itself. This makes it easy to set up a group of Tasks where the same individual is the designated owner, responsible for the completion of a Task and all subTasks.

The getDetails method is another example of Chain of Responsibility behavior, but it behaves somewhat differently. It calls the getDetails method of each parent until it reaches a Task or Project that is identified as a terminal node. This means that getDetails returns a series of Strings representing all the details for a particular Task chain.

40