Consider the Show interface and the two implementing classes Movie and Concert. Create a class SponsoredConcert
that is a subtype of Concert
with two additional pieces of data: a sponsor name (String
) and a sponsor time (int
) that represents the number of minutes the sponsor is allocated to advertise as part of the show. A call to description()
on an instance of SponsoredConcert
should include the title and performer of the concert, along with the name of the sponsor. A call to time()
on an instance of SponsoredConcert
should return the time of the concert plus the time allocated to the sponsor.
Change the code of Concert
so that the field aPerformer
is private
. What are possible solutions for accessing this information?
Create an abstract class AbstractShow
that groups all the fields that Concert
and Movie
have in common. Refactor your class hierarchy to use this abstract class with as tight encapsulation as possible.
Draw a class diagram of the refactored design completed in Exercise 3, then extend the diagram to show how CompositeShow
(a composite) and IntroducedShow
(a decorator) would integrate the design.
We want to ensure that calling method description()
on an instance of any type of Show
returns a string with the following format:
$TITLE$: [...] ($TIME$ minutes)
where $TITLE
is a placeholder for the title of the show, and $TIME
is a placeholder for the total running time of the show. Implement this functionality by applying the Template Method design pattern.
Draw a UML sequence diagram that model the sequence of calls that results from an invocation of method description
on an instance of SponsoredConcert
. To clarify which implementation of a method is used, name the call using the convention Class#Method
, so that for example a call to method time()
of class SponsoredConcert
would be labeled as SponsoredConcert#time()
.
Consider the class AbstractShow
created as part of Exercise 3. Add a method setTitle(String)
in AbstractShow
to set the title of the show. Because the title of a movie does not change after the movie is released, override setTitle
to throw an UnsupportedOperationException. Similarly, implement a method setTime
in AbstractShow
with an input precondition of > 0
, and override this method in Movie
to have the precondition > 10
. Does class Movie
respect the Liskov Substitution Principle? Support your answer with a piece of demonstration client code.
Assume class AbstractShow
provides a method setTime(int minutes)
. Add an additional method setTime(int hours, int minutes)
that sets the time of the show as hours * 60 + minutes
. Is this a case of overloading or overriding? Now remove the implementation of setTime(int hours, int minutes)
and add it to class Movie
instead. Is this a case of overloading or overriding? Does it make a difference whether we place this method in AbstractShow
or Movie
?
We wish to add a recommendation feature to our Show
type hierarchy, where Show
instances can hold a reference to a "recommended" show (if a person likes a given show). For this purpose, add a field Show aRecommended
to class AbstractShow
, together with public methods Show setRecommended(Show)
and Show getRecommended()
. For movies, we wish to constrain recommendations to movies only, so that movies can only hold recommendations to other movies. Override methods setRecommended
and getRecommended
in class Movie
to only take Movie
as parameter and return Movie
, respectively. Does this design respect the Liskov Substitution Principle? Support your answer with a piece of demonstration client code.
Make the Show
class hierarchy Cloneable
so that it is possible to clone instances of Concert
, Movie
, or SponsoredConcert
.
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-2021