Fabryka klas: znaczniki na wykresie

W poprzednim ćwiczeniu powstała klasa Plot. Umożliwia ona rysowanie wykresu punktowego dzięki metodzie Plot.scatter()

Celem tego ćwiczenia jest umożliwienie dynamicznego tworzenia graficznych symboli, odpowiadającym punktom na wykresie. W tym celu wykorzystasz wzorzec projektowy fabryka klas.

Zadanie

Napisz moduł markers_factory.py zawierający fabrykę klas produkującą znaczniki do wykresu punktowego i wykorzystaj go w klasie Plot. Poprawne rozwiązanie powinno umożliwiać rysowanie wykresu punktowego z dowolnymi znacznikami zdefiniowanymi przez użytkownika; bez konieczności edytowania klasy Plot.

Klasy - znaczniki

Napisz AbstractMarker oraz dziedziczące po niej znaczniki: CircleMarker (koło) oraz SquareMarker (kwadrat).

Klasy - producenci

Instancje tych klas produkowane będą w fabryce MarkerFactory, która zwróci marker dla zadanego symbolu, np CircleMaker dla symbolu `o`. Aby umożliwić zautomatyzowaną produkcję znaczników, kompletna implementacja fabryki wymaga również stworzenia klas-procucentów (makers), czyli CircleMakerMaker, SquareMakerMaker, itd. Producenci powinni dziedziczyć po wspólnej abstrakcyjnej klasie bazowej.

Program testowy

Końcowa implementacja musi poprawnie działać napisaną wcześniej klasą Plot. Zauważ, że poniższy program testowy wymaga napisania własnego znacznika, odpowiedniego producenta (maker) i zarejestrowania tego ostatniego w fabryce.

Na przykład, MyMaker może być rombem (DiamondMarker)

import math
from plot import Axes, Plot
from svg_shapes import Style
from markers_factory import AbstractMarker, AbstractMaker

class MyMakerMaker(AbstractMaker):
    # Tu zaimplementuj swój znacznik
    pass

class MyMaker(AbstractMarker):
    # Tu zaimplementuj maker do znacznika
    pass

axes = (
    Axes("ax1", 80, 40, 580, 260)
    .bottom(0.0, 360)
    .left(-1.1, 1.1)
    .top(0.0, 360)
    .right(-1.1, 1.1)
    .with_xticks(6)
    .with_yticks(4)
    .with_grid(True)
    .with_stroke("black")
    .with_stroke_width(1.5)
)

x = [i for i in range(0, 370, 10)]
ys2 = [math.sin(v*3.14159/180.0)**2 for v in x]

pl = Plot(axes)
pl.define_new_marker('M', MyMakerMaker())
sin2_style = Style(fill="#a6cee3", stroke_width=1.5, stroke="#1f78b4")

pl.scatter(x, ys2, marker="M", style=sin2_style)
pl.save_fig("plot_with_marker.svg")

Wynik powinien przypominać wykres z poprzedniego ćwiczenia.