Card 07/ 08
Practice: A Facade for a Home Cinema
Projector, amplifier, streaming player and lights, with watch_movie() and end_movie().
A home cinema is a natural Facade, and this exercise asks you to write one and then say what it leaves open. Four classes are involved. Projector and Amplifier each have on() and off(), and the amplifier has set_volume(level). StreamingPlayer has play(title) and stop(). Lights has dim(percent).
- Write
HomeCinemawithwatch_movie(title), which dims the lights to 10%, turns on the projector and amplifier, sets the volume to 5 and plays the film, andend_movie(), which reverses it. - Halfway through a film, the viewer wants the volume at 8. The facade has no volume method. How do they change it?
Show a solution
class Projector:
def on(self) -> None:
print("projector on")
def off(self) -> None:
print("projector off")
class Amplifier:
def on(self) -> None:
print("amplifier on")
def set_volume(self, level: int) -> None:
print(f"amplifier volume {level}")
def off(self) -> None:
print("amplifier off")
class StreamingPlayer:
def play(self, title: str) -> None:
print(f"playing {title}")
def stop(self) -> None:
print("player stopped")
class Lights:
def dim(self, percent: int) -> None:
print(f"lights at {percent}%")
class HomeCinema:
def __init__(self, projector: Projector, amplifier: Amplifier, player: StreamingPlayer, lights: Lights) -> None:
self._projector = projector
self._amplifier = amplifier
self._player = player
self._lights = lights
def watch_movie(self, title: str) -> None:
self._lights.dim(10)
self._projector.on()
self._amplifier.on()
self._amplifier.set_volume(5)
self._player.play(title)
def end_movie(self) -> None:
self._player.stop()
self._amplifier.off()
self._projector.off()
self._lights.dim(100)
amplifier = Amplifier()
cinema = HomeCinema(Projector(), amplifier, StreamingPlayer(), Lights())
cinema.watch_movie("Brief Encounter")
amplifier.set_volume(8)
cinema.end_movie()lights at 10%
projector on
amplifier on
amplifier volume 5
playing Brief Encounter
amplifier volume 8
player stopped
amplifier off
projector off
lights at 100%The facade holds the two sequences, and end_movie runs them in reverse, so the lights come up last. The volume change does not need a new facade method: the client keeps its reference to the amplifier and calls set_volume(8) directly, as the output shows between the two sequences. The extra arrow from the client to the amplifier in the diagram is that call. A facade that tried to offer every amplifier setting would be the subsystem again, with a longer name.
← → move through sections and cards