Skip to content

Latest commit

 

History

History
189 lines (123 loc) · 8.63 KB

File metadata and controls

189 lines (123 loc) · 8.63 KB

Chapter 6 Practice Exercises

Exercise 1

Consider interface Show and the two implementing classes Movie and Concert. Apply the Composite design pattern to provide support for a kind of show that is a combination of between two and five shows, inclusively. Write a client program that creates a show that consists of a concert followed by two movies, where the two movies are, together, represented by a single Show object.

Solution (and more)

Exercise 2

Extend the design produced in Exercise 1 to apply the Decorator design pattern so as to provide a IntroducedShow feature, which consists of a show introduced by a speaker giving a fixed-time speech (e.g., 10 minutes). In client code, create a Show object that is an introduced version of the show created in Exercise 1, where the second movie is also introduced (so, two speakers, one presenting the entire show, and one presenting the second movie).

Solution (and more)

Exercise 3

Draw a class diagram of your combined design for exercises 1 and 2.

Solution (and more)

Exercise 4

Draw an object diagram of the object graph created as part of exercise 2.

Solution (and more)

Exercise 5

Draw a sequence diagram that illustrates the sequence of method calls that results from a call to description on the root Show for the object graph depicted in Exercise 5.

Solution (and more)

Exercise 6

We add the following requirement to the system created and documented as part of Exercises 1-5: We need a way to obtain all the shows in a composite show so that a client can "unpack" a composite. Implement this requirement using an iterator in a way that does not change the Show interface.

Solution (and more)

Exercise 7

Implement a variant of the feature described in Exercise 7, but this time by modifying the Show interface.

Solution (and more)

Exercise 8

Create a new class DoubleBill that represents a sequence of exactly two movies, but that is not a Decorator. Make sure your implementation respects the requirement expressed in Exercise 8.

Solution (and more)

Exercise 9

Implement a copy constructor for Concert, Movie, and DoubleBill, in this order. Assume all Show object need to be copied deeply (which includes making copies of the object stored in fields of any type except primitive types and String). Then implement a copy constructor for IntroducedShow. Why is the solution problematic?

Solution (and more)

Exercise 10

Add support for polymorphic copying into the Show type hierarchy. Add a copy() method to the Show interface with the semantics that it does a deep copy of the object as defined for Exercise 10.

Solution (and more)

Exercise 11

Implement methods equals and hashCode on all implementing classes of Show. Consider that two composite shows are equals if they contain equal shows in the same sequence.

Solution (and more)

Exercise 12

Using JUnit, write a unit test that checks that a copy of the object graph created as part of exercise 2 is a correct deep copy.

Solution (and more)

Exercise 13

Complete class Program so that the requirements are met, including by creating a new class that represents the absence of a show ("Null show"). It should be possible to copy instances of a Null show to respect the contracts of the Show.copy() and Program.get() methods, but clients should also be able to determine if a given show is a Null show.

/**
 * Class responsible for managing a program that consists of various shows
 * presented on different days of one week. Each day of the week must be
 * associated with exactly one Show object. If there is not show on a given day,
 * a special object of type show is used to represent a "non-show".
 */
public class Program {

	public enum Day {
		MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
	}

	private final EnumMap<Day, Show> aShows = new EnumMap<>(Day.class);

	public Program() {
		// TODO
	}

	/**
	 * Clear the program by removing all existing shows.
	 */
	public void clear() {
		// TODO
	}

	/**
	 * Adds a new show to the program. Overrides any existing show on that day.
	 * 
	 * @param pShow The show to add.
	 * @param pDay  The day when the show takes place.
	 */
	public void add(Show pShow, Day pDay) {
		assert pShow != null && pDay != null;
		// TODO
	}

	/**
	 * Removes a show from the program.
	 * 
	 * @param pDay The day when we want to zap the show.
	 */
	public void remove(Day pDay) {
		assert pDay != null;
		// TODO
	}

	/**
	 * @param pDay The day of the requested show.
	 * @return A copy of the show on a given day.
	 */
	public Show get(Day pDay) {
		assert pDay != null;
		return null;// TODO
	}

	@Override
	public String toString() {
		StringBuilder result = new StringBuilder();
		for (Day day : aShows.keySet()) {
			if (aShows.containsKey(day)) {
				result
					.append(String.format("%9s", day.name()))
					.append(": ")
					.append(aShows.get(day).description())
					.append("\n");
			}
		}
		return result.toString();
	}
}

Solution (and more)

Exercise 14

Apply the Command design pattern so that is is possible to clear a program, add shows to it, and remove shows from it using Command objects. Write a sample client code that adds two movies to a program, removes one, then clears the program (from the remaining movie). Implement commands using anonymous classes (which will require you to write factory methods for them).

Solution (and more)

Exercise 15

Extend the design created in Exercise 14 to allow commands to be undoable. Extend the client code of Exercise 14 to undo all commands executed, and verify that after each command can be properly undone.

Solution (and more)

Exercise 16

Build a CommandProcessor that is an abstraction that allows clients to execute commands, store executed commands, and undo the last executed command. Ensure your design respects the Law of Demeter.

Solution (and more)

Exercise 17

Extends the CommandProcessor so that is supports redoing commands (that is, executing undone commands).

Solution (and more)

Exercise 18

Modify your design so that the operations of a CommandProcessor are encapsulated within a Program. In other words, client code should be able to once again call add remove and clear on an instance of Program to perform these actions, but the actions would be stored as commands within a program and be undoable through an undoLast() method added to the interface of Program. How can you avoid pushing Program towards a God class responsible for two different things: managing a program and managing a stack of commands?

Solution (and more)


Creative Commons License

Unless otherwise noted, the content of this repository is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

Copyright Martin P. Robillard 2019-2026