Builder

A builder tervezési minta szétválasztja a reprezentációt és az őt felépítő (komplex) logikát.

Bevezető példa: StringBuilder

Számos programnyelvben a string egy olyan objektum, amit gyakran fűzünk össze másik stringekkel, viszont ez a művelet meglehetősen erőforrás igényes. Amennyiben a

for(int i=0; i<100; i++)
    result = result + string(i) + " és ";

minden egyes + műveleténél létre kell hozni egy új (az esetek nagy részében ideiglenes) string objektumot a részeredmény tárolására, akkor az igen nagy erőforrás pazarlás. Erre jött létre a StringBuilder, melynek sorban meg lehet mondani, hogy miket fűzzön hozzá a stringhez, de a tényleges string objektum csak akkor jön létre, amikor készen vagyunk. Addig a tartalma másik formában tárolódik, úgy, hogy ahhoz sokkal könnyebb legyen hozzáfűzni.

(Megjegyzés: Qt alatt az & string összefűző művelet olyan, mint a +, csak pont egy ilyen StringBuilderes megoldásra fordul le.)

Ebben a példában a StringBuilder egy olyan osztály, mely stringek felépítését végzi. Amikor pedig készen van, akkor az ő feladata véget is ért.

Részletek

Ezt a tervezési mintát akkor használjuk, ha az osztály felépítése (1) összetett és/vagy erőforrás igényes, és a használat közben a felépítő funkciókra már nincsen szükség, vagy (2) a pontos belső felépítés cserélhető az interfésztől függetlenül.

Az 1. esetre példa egy labirintusos játék pályája, mely egy jókora gráf formájában áll össze. Amikor már készen van, akkor már csak használjuk, így a térkép összerakására csak a létrehozáskor van szükség. Ilyenkor a Builder osztály sorban megkapja, hogy mik és hol vannak a játéktéren, létrehozza a szükséges mezőket, majd az átjáróknak megfelelően összekötögeti őket. Végül amikor minden a helyén van, visszaadja az egész játékteret, amit ezután már nem módosítunk az átjárók és mezőtípusok szempontjából.

A 2. esetre példa az, amikor egy adatforrásból (pl. fájlból) olvassuk be egy összetett adatstruktúrát, de a fájlban sokkal több adat van, mint amennyire szükségünk van. Attól függően, hogy melyik buildert választjuk, el tudjuk dönteni, hogy milyen részletezettségi szintű adatstruktúrát akarunk felépíttetni a fájl alapján. Ebben az esetben többféle Builder osztály van (egy közös ősből leszármaztatva), így a ténylegesen létrehozott eredmény attól függ, éppen melyik Buildert használtuk. (Ez közel áll a factory method mintához is.)

Mindkét esetben a Builder osztály csak a felépítésért felelős, utána már nincsen rá szükség.

További előnyök

Megjegyzések

Példa: Reader és Builder objektumok

Tegyük fel, hogy több fájlformátumból tudunk beolvasni egy bonyolultabb adatstruktúrát. Ekkor a felépítést egy builderrel végezhetjük, amit átadunk egy a konkrét fájlformátumot ismerő, beolvasó objektumnak (reader). A reader olvassa a fájlt és használja a buildert, hogy a végén a teljes adatstruktúra előálljon.

(Amennyiben többféle belső reprezentációra is van lehetőség, a readernek átadott konkrét builderrel határozhatjuk meg, hogy milyen adatstruktúra épüljön fel.)

Egyéb példák

Szerzők, verziók: Csorba Kristóf