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

Composite

The example demonstrates how to use the Composite pattern to calculate the time required to complete a project or some part of a project. The example has four principal parts:

Deliverable

A class that represents an end product of a completed Task.

Project – The class used as the root of the composite, representing the entire project.

ProjectItem

This interface describes functionality common to all items that can be part of a project. The

getTimeRequired method is defined in this interface.

Task – A class that represents a collection of actions to perform. The task has a collection of ProjectItem objects.

The general functionality available to every object that can be part of a project is defined in the ProjectItem interface. In this example, there is only a single method defined: getTimeRequired.

Example A.144 ProjectItem.java

1.import java.io.Serializable;

2.public interface ProjectItem extends Serializable{

3.public double getTimeRequired();

4.}

Since the project items can be organized into a tree structure, two kinds of classes are ProjectItems. The Deliverable class represents a terminal node, which cannot reference other project items.

Example A.145 Deliverable.java

1.import java.io.Serializable;

2.public interface ProjectItem extends Serializable{

3.public double getTimeRequired();

4.}

The Project and Task classes are nonterminal or branch nodes. Both classes keep a collection of ProjectItems that represent children: associated tasks or deliverables.

Example A.146 Project.java

1.import java.util.ArrayList;

2.import java.util.Iterator;

3.public class Project implements ProjectItem{

4.private String name;

5.private String description;

6.private ArrayList projectItems = new ArrayList();

8.public Project(){ }

9.public Project(String newName, String newDescription){

10.name = newName;

11.description = newDescription;

12.}

13.

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

15.public String getDescription(){ return description; }

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

17.public double getTimeRequired(){

18.double totalTime = 0;

19.Iterator items = projectItems.iterator();

20.while(items.hasNext()){

21. ProjectItem item = (ProjectItem)items.next();

22. totalTime += item.getTimeRequired();

23.}

24.return totalTime;

25.}

26.

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

28.public void setDescription(String newDescription){ description = newDescription; }

30.public void addProjectItem(ProjectItem element){

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

32. projectItems.add(element);

296

33.}

34.}

35.public void removeProjectItem(ProjectItem element){

36.projectItems.remove(element);

37.}

38.}

Example A.147 Project.java

1.import java.util.ArrayList;

2.import java.util.Iterator;

3.public class Project implements ProjectItem{

4.private String name;

5.private String description;

6.private ArrayList projectItems = new ArrayList();

8.public Project(){ }

9.public Project(String newName, String newDescription){

10.name = newName;

11.description = newDescription;

12.}

13.

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

15.public String getDescription(){ return description; }

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

17.public double getTimeRequired(){

18.double totalTime = 0;

19.Iterator items = projectItems.iterator();

20.while(items.hasNext()){

21. ProjectItem item = (ProjectItem)items.next();

22. totalTime += item.getTimeRequired();

23.}

24.return totalTime;

25.}

26.

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

28.public void setDescription(String newDescription){ description = newDescription; }

30.public void addProjectItem(ProjectItem element){

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

32. projectItems.add(element);

33.}

34.}

35.public void removeProjectItem(ProjectItem element){

36.projectItems.remove(element);

37.}

38.}

Example A.148 Task.java

1.import java.util.ArrayList;

2.import java.util.Iterator;

3.public class Task implements ProjectItem{

4.private String name;

5.private String details;

6.private ArrayList projectItems = new ArrayList();

7.private Contact owner;

8.private double timeRequired;

9.

10.public Task(){ }

11.public Task(String newName, String newDetails,

12.Contact newOwner, double newTimeRequired){

13.name = newName;

14.details = newDetails;

15.owner = newOwner;

16.timeRequired = newTimeRequired;

17.}

18.

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

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

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

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

23.public double getTimeRequired(){

24.double totalTime = timeRequired;

25.Iterator items = projectItems.iterator();

26.while(items.hasNext()){

27. ProjectItem item = (ProjectItem)items.next();

28. totalTime += item.getTimeRequired();

29.}

297

30.return totalTime;

31.}

32.

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

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

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

36.public void setTimeRequired(double newTimeRequired){ timeRequired = newTimeRequired; }

38.public void addProjectItem(ProjectItem element){

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

40. projectItems.add(element);

41.}

42.}

43.public void removeProjectItem(ProjectItem element){

44.projectItems.remove(element);

45.}

46.}

The getTimeRequired method shows how the Composite pattern runs. To get the time estimate for any part of the project, you simply call the method getTimeRequired for a Project or Task object. This method behaves differently depending on the method implementer:

Deliverable: Return 0.

Project or Task: Return the sum of the time required for the object plus the results of calling the getTimeRequired method for all ProjectItems associated with this node.

The Contact interface and ContactImpl class provide support code to represent the owner of a task or deliverable.

Example A.149 Contact.java

1.import java.io.Serializable;

2.public interface Contact extends Serializable{

3.public static final String SPACE = " ";

4.public String getFirstName();

5.public String getLastName();

6.public String getTitle();

7.public String getOrganization();

8.

9.public void setFirstName(String newFirstName);

10.public void setLastName(String newLastName);

11.public void setTitle(String newTitle);

12.public void setOrganization(String newOrganization);

13.}

Example A.150 ContactImpl.java

1.public class ContactImpl implements Contact{

2.private String firstName;

3.private String lastName;

4.private String title;

5.private String organization;

6.

7.public ContactImpl(){}

8.public ContactImpl(String newFirstName, String newLastName,

9.String newTitle, String newOrganization){

10. firstName = newFirstName;

11. lastName = newLastName;

12. title = newTitle;

13. organization = newOrganization;

14. }

15.

16.public String getFirstName(){ return firstName; }

17.public String getLastName(){ return lastName; }

18.public String getTitle(){ return title; }

19.public String getOrganization(){ return organization; }

21.public void setFirstName(String newFirstName){ firstName = newFirstName; }

22.public void setLastName(String newLastName){ lastName = newLastName; }

23.public void setTitle(String newTitle){ title = newTitle; }

24.public void setOrganization(String newOrganization){ organization = newOrganization; }

26.public String toString() {

27.return firstName + SPACE + lastName;

298

28.}

29.}

This example uses a small demonstration project to illustrate the Command pattern. To simplify the task of managing a stored copy of the project information, the DataCreator class creates a sample project and serializes it to a file.

Example A.151 DataCreator.java

1.import java.io.Serializable;

2.import java.io.ObjectOutputStream;

3.import java.io.FileOutputStream;

4.import java.io.IOException;

5.public class DataCreator {

6.private static final String DEFAULT_FILE = "data.ser";

8.public static void main(String [] args){

9.String fileName;

10.if (args.length == 1){

11. fileName = args[0];

12.}

13.else{

14. fileName = DEFAULT_FILE;

15.}

16.serialize(fileName);

17.}

18.

19.public static void serialize(String fileName){

20.try{

21. serializeToFile(createData(), fileName);

22.}

23.catch (IOException exc){

24. exc.printStackTrace();

25.}

26.}

28.private static Serializable createData(){

29.Contact contact1 = new ContactImpl("Dennis", "Moore", "Managing Director", "Highway

Man, LTD");

30.Contact contact2 = new ContactImpl("Joseph", "Mongolfier", "High Flyer", "Lighter

than Air Productions");

31.Contact contact3 = new ContactImpl("Erik", "Njoll", "Nomad without Portfolio",

"Nordic Trek, Inc.");

32. Contact contact4 = new ContactImpl("Lemming", "", "Principal Investigator", "BDA"); 33.

34.Project project = new Project("IslandParadise", "Acquire a personal island

paradise");

35.Deliverable deliverable1 = new Deliverable("Island Paradise", "", contact1);

36.Task task1 = new Task("Fortune", "Acquire a small fortune", contact4, 11.0);

37.Task task2 = new Task("Isle", "Locate an island for sale", contact2, 7.5);

38.Task task3 = new Task("Name", "Decide on a name for the island", contact3, 3.2);

39.project.addProjectItem(deliverable1);

40.project.addProjectItem(task1);

41.project.addProjectItem(task2);

42.project.addProjectItem(task3);

43.

44.Deliverable deliverable11 = new Deliverable("$1,000,000", "(total net worth after

taxes)", contact1);

45.Task task11 = new Task("Fortune1", "Use psychic hotline to predict winning lottery

numbers", contact4, 2.5);

46.Task task12 = new Task("Fortune2", "Invest winnings to ensure 50% annual interest",

contact1, 14.0);

47.task1.addProjectItem(task11);

48.task1.addProjectItem(task12);

49.task1.addProjectItem(deliverable11);

51.Task task21 = new Task("Isle1", "Research whether climate is better in the Atlantic

or Pacific", contact1, 1.8);

52.Task task22 = new Task("Isle2", "Locate an island for auction on EBay", contact4,

5.0);

53.Task task23 = new Task("Isle2a", "Negotiate for sale of the island", contact3, 17.5);

54.task2.addProjectItem(task21);

55.task2.addProjectItem(task22);

56.task2.addProjectItem(task23);

57.

58.Deliverable deliverable31 = new Deliverable("Island Name", "", contact1);

59.task3.addProjectItem(deliverable31);

299