Builder (design sample)

from Wikipedia, the free encyclopedia

The builder (English builder ) is a design pattern in the field of software development . It belongs to the category of the generation pattern (English creational patterns ) and the construction separates complex objects of their representations, whereby the same design processes can be reused. The pattern is one of the so-called GoF patterns ( Gang of Four , see Gang of Four ).

use

The use of the builder design pattern is advisable if

  • different representations should exist for a complex object,
  • the construction of a complex object should be independent of the creation of the components or
  • the construction process requires an internal state that should be hidden from a client.

Typical applications are e.g. B. Application programs for conversion .

UML class diagram: Builder

actors

One can distinguish between four actors: Direktor, Erbauer, KonkreterErbauerand Produkt. The builder specifies an abstract interface for creating the parts of a complex object. The concrete builder creates the parts of the complex object by implementing the interface. He also defines and manages the representation of the product he creates. It also offers an interface for reading out the product.

The director constructs a complex object using the builder's interface. The director works closely with the builder : he knows which construction sequence the builder can handle or need. The director thus decouples the construction process from the client . The product represents the complex object to be constructed.

advantages

The implementations of the construction and the representations are isolated. The builders hide their internal representation from the director. New representations can easily be inserted through new concrete builder classes. The construction process is controlled in a dedicated place (in the director); Later changes - for example a multi-phase construction process instead of a single-phase construction - can be implemented without changing the client.

disadvantage

There is a close link between the product, the specific builder and the classes involved in the construction process.

variant

You can also let the product itself implement the builder interface. This saves u. U. some classes. The created product “drags” the builder interface with it all its life, so that product parts can later be added from the outside.

Use in analysis

This pattern is rarely used in software analysis because of the difficult metaphor.

The variant in which an object itself provides procedures for adding additional parts is advantageous in pipeline-like business processes. The business process as director instructs the document as builder to create new parts and hook them into itself. For example, a file management system can attach notes to a file run in individual steps.

example

Stock exchange software records stock prices in a text file in the following format: For each stock corporation, the security identification number, name of the stock corporation, price and the number of items traded are saved in one line, separated by spaces:

515100 BASF          36,84  2850400
803200 Commerzbank 6,71  17231300
...

Now this format is to be converted into a format such as CSV or XML . If the semicolon is used as a separator in CSV format, the above file should be converted into the following, for example:

515100;BASF;36,84;2850400
803200;Commerzbank;6,71;17231300

In XML format, however, the result of the conversion could look like this:

<Aktienkurse>
        <Aktie>
                <WKN>515100</WKN>
                <Name>BASF</Name>
                <Kurs>36,84</Kurs>
                <Stueckzahl>2850400</Stueckzahl>
        </Aktie>
        <Aktie>
                <WKN>803200</WKN>
                <Name>Commerzbank</Name>
                <Kurs>6,71</Kurs>
                <Stueckzahl>17231300</Stueckzahl>
        </Aktie>
</Aktienkurse>

The following C ++ program shows the use of the builder pattern in an application for data format conversion, which can easily be expanded to include additional output formats. The director (class KursdatenUmwandler) knows how to read and parse data in legacy format. He knows a builder who can translate parsed parts into his respective format. All concrete builders are concrete subclasses of the abstract class KursdatenBauer. For example, the class translates XMLKursdatenBauerparsed lines into an XML format.

The client can inform the director of the specific builder at runtime. So the output format can be changed at runtime.

To support a new output format, the class only needs to be KursdatenBauerimplemented accordingly by a specific subclass, e.g. B. by LaTeXKursdatenBauer.

The following is important with this pattern: It is not only the individual parts that are produced that have complexity (this is taken care of by the specific producers), but also the whole to be produced is a complex object, which the director takes care of producing. The director is therefore the “specialist” for the creation of the product. He alone knows the necessary individual steps. In the example, he alone knows how to parse the old format and how to assemble the new format from it.

#include <iostream>
#include <memory>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::shared_ptr;
using std::string;

// Abstrakter Erbauer:

class KursdatenBauer {
public:
    virtual void KursdatenSchreiben(const string &wkn, const string &name,
                                                                    const string &kurs,
                                                                    const string &stueckzahl) = 0;

    virtual void SchreibenInitialisieren() {}

    virtual void SchreibenBeenden() {}
};

// Konkreter Erbauer für CSV-Dateien:

class CSVKursdatenBauer : public KursdatenBauer {
    DatenRepraesentation &repr_;

public:
    CSVKursdatenBauer(DatenRepraesentation &arepr) : repr_(arepr) {}

    // Hier entsteht das Produkt, der Einfachheit halber auf die
    // Standardausgabe geschrieben. (Es könnte auch in einen Stream
    // geschrieben werden, der im Konstruktor übergeben wird.)
    virtual void KursdatenSchreiben(const string &wkn, const string &name,
                                                                    const string &kurs,
                                                                    const string &stueckzahl) {
        repr_.anhaengen(wkn)
                .anhaengen(";")
                .anhaengen(name)
                .anhaengen(";")
                .anhaengen(kurs)
                .anhaengen(";")
                .anhaengen(stueckzahl);
    }

    virtual void SchreibenInitialisieren() { repr_.loeschen(); }
};

// konkreter Erbauer für XML-Dateien:

class XMLKursdatenBauer : public KursdatenBauer {
    DatenRepraesentation &repr_;

public:
    XMLKursdatenBauer(DatenRepraesentation &arepr) : repr_(arepr) {}

    virtual void KursdatenSchreiben(const string &wkn, const string &name,
                                                                    const string &kurs,
                                                                    const string &stueckzahl) {
        repr_.anhaengen("\t<Aktie>").anhaengen("\n");
        repr_.anhaengen("\t\t<WKN>").anhaengen(wkn).anhaengen("</WKN>\n");
        repr_.anhaengen("\t\t<Name>").anhaengen(name).anhaengen("</Name>\n");
        repr_.anhaengen("\t\t<Kurs>").anhaengen(kurs).anhaengen("</Kurs>\n");
        repr_.anhaengen("\t\t<Stueckzahl>").anhaengen(stueckzahl).anhaengen("</Stueckzahl>\n");
        repr_.anhaengen("\t</Aktie>").anhaengen("\n");
    }

    virtual void SchreibenInitialisieren() {
        repr_.loeschen();
        repr_.anhaengen("<Aktienkurse>").anhaengen("\n");
    }

    virtual void SchreibenBeenden() {
        repr_.anhaengen("</Aktienkurse>").anhaengen("\n");
    }
};

// Produkt

class DatenRepraesentation {
    string text;

public:
    DatenRepraesentation &anhaengen(const string &teil) {
        text += teil;
        return (*this);
    }

    void ausgeben() {
        cout << text << endl;
    }

    void loeschen() {
        text.clear();
    }
};

// Direktor:

class KursdatenUmwandler {
    shared_ptr<KursdatenBauer> _kursdatenBauer;

public:
    void KursdatenBauerSetzen(shared_ptr<KursdatenBauer> kb) {
        _kursdatenBauer = kb;
    }

    void KursdatenParsenUndSchreiben() {
        _kursdatenBauer->SchreibenInitialisieren();
        // Zeile für Zeile von STDIN lesen und in geeignete Teile zerlegen
        while (!cin.eof()) {
            string wkn, name, kurs, stueckzahl;
            // lesen:
            cin >> wkn >> name >> kurs >> stueckzahl;
            if (wkn.empty()) {
                break;
            }
            // schreiben:
            _kursdatenBauer->KursdatenSchreiben(wkn, name, kurs, stueckzahl);
        }
        _kursdatenBauer->SchreibenBeenden();
    }
};

// Klient:

int main() {
    DatenRepraesentation repraesentation;
    shared_ptr<KursdatenBauer> csvKursdatenBauer(new CSVKursdatenBauer(repraesentation));
    shared_ptr<KursdatenBauer> xmlKursdatenBauer(new XMLKursdatenBauer(repraesentation));
    KursdatenUmwandler kursdatenUmwandler;

    kursdatenUmwandler.KursdatenBauerSetzen(xmlKursdatenBauer);
    // oder
    // kursdatenUmwandler.KursdatenBauerSetzen(csvKursdatenBauer);
    kursdatenUmwandler.KursdatenParsenUndSchreiben();

    // Aktion mit dem Produkt ausführen
    repraesentation.ausgeben();
}

Related design patterns

The abstract factory is similar to the builder because it can also create complex objects. The focus here is not on the structure, but on the abstraction from the specific type of the objects created. The builder often creates a compound word (design pattern) . In the case of conversion applications, the director - or even the builder - is often a visitor or possibly an interpreter (design sample) of the structure to be converted.

Web links

Commons : Builder  - album with pictures, videos and audio files

Individual evidence

  1. Erich Gamma , Richard Helm , Ralph Johnson , John Vlissides : Design pattern . 5th edition. Addison-Wesley, 1996, ISBN 3-8273-1862-9 , pp. 119 .
  2. ^ Karl Eilebrecht, Gernot Starke: Patterns compact. Design patterns for effective software development . 3. Edition. Spektrum Akademischer Verlag, 2010, ISBN 978-3-8274-2525-6 , pp. 29 , doi : 10.1007 / 978-3-8274-2526-3 .