The payoff: with 2 shape classes and 2 renderer classes we cover all 2 x 2 combinations without a single extra class. A naive design would need VectorCircle, RasterCircle, VectorSquare, RasterSquare and would keep growing.
Implement the helper draw_all(shapes): draw every shape already bound to some renderer and return the list of result strings in order.
class Renderer:
def render_circle(self, radius):
raise NotImplementedError
def render_square(self, side):
raise NotImplementedError
class VectorRenderer(Renderer):
def render_circle(self, radius):
return "vector circle r=" + str(radius)
def render_square(self, side):
return "vector square s=" + str(side)
class RasterRenderer(Renderer):
def render_circle(self, radius):
return "raster pixels for circle r=" + str(radius)
def render_square(self, side):
return "raster pixels for square s=" + str(side)
class Shape:
def __init__(self, renderer):
self.renderer = renderer
def set_renderer(self, renderer):
self.renderer = renderer
def draw(self):
raise NotImplementedError
class Circle(Shape):
def __init__(self, renderer, radius):
super().__init__(renderer)
self.radius = radius
def draw(self):
return self.renderer.render_circle(self.radius)
class Square(Shape):
def __init__(self, renderer, side):
super().__init__(renderer)
self.side = side
def draw(self):
return self.renderer.render_square(self.side)
def draw_all(shapes):
"""Draw every shape in the list and return the list of result strings."""
# TODO: return [shape.draw() for shape in shapes]
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
The payoff: with 2 shape classes and 2 renderer classes we cover all 2 x 2 combinations without a single extra class. A naive design would need VectorCircle, RasterCircle, VectorSquare, RasterSquare and would keep growing.
Implement the helper draw_all(shapes): draw every shape already bound to some renderer and return the list of result strings in order.
Press Run Tests or ββ© to check your solution.