ExerciseDifficulty: Advanced2 min

Practice: Remote Controls and Devices

Basic and advanced remotes, for a TV, a radio and a projector.

Remote controls for several devices are a natural Bridge, and this exercise asks you to design one and count what it saves. A basic remote turns a device on and off and raises the volume. An advanced remote does the same and can also mute. Both must work a TV, a radio and a projector.

  1. Name the abstraction and the implementor.
  2. Write the classes, with each remote holding a device.
  3. How many concrete classes does the design need, and how many would one subclass per pair need?
  4. A fourth device is added. How many new classes does each design need?
Show a solution
Remotes and devices as two hierarchies
py
from abc import ABC, abstractmethod


class Device(ABC):
    def __init__(self) -> None:
        self.on = False
        self.volume = 10

    @abstractmethod
    def name(self) -> str: ...


class Tv(Device):
    def name(self) -> str:
        return "TV"


class Radio(Device):
    def name(self) -> str:
        return "radio"


class Projector(Device):
    def name(self) -> str:
        return "projector"


class Remote:
    def __init__(self, device: Device) -> None:
        self._device = device

    def toggle_power(self) -> None:
        self._device.on = not self._device.on
        print(f"{self._device.name()} on: {self._device.on}")

    def volume_up(self) -> None:
        self._device.volume += 1
        print(f"{self._device.name()} volume: {self._device.volume}")


class AdvancedRemote(Remote):
    def mute(self) -> None:
        self._device.volume = 0
        print(f"{self._device.name()} muted")


Remote(Tv()).toggle_power()
Remote(Radio()).volume_up()
advanced = AdvancedRemote(Projector())
advanced.toggle_power()
advanced.mute()

remotes, devices = 2, 3
print(f"classes now: {remotes * devices} without a bridge, {remotes + devices} with one")
print(f"a fourth device adds {remotes} classes without a bridge, 1 with one")
OutputRan with python:3.12-slim (Python 3.12.13)
TV on: True
radio volume: 11
projector on: True
projector muted
classes now: 6 without a bridge, 5 with one
a fourth device adds 2 classes without a bridge, 1 with one
Either remote works any device, because it holds a `Device` and not a particular one.

The remote is the abstraction and the device is the implementor. The bridge needs five classes, two remotes and three devices, against six for one subclass per pair. A fourth device is one new class with the bridge, and two without it, a basic and an advanced remote for that device. The example has a limit: real remotes are often paired to one brand, which is a case where the two dimensions are not independent.