Builder Builder - motivácia Motivácia sitemap v rôznych výstupoch HTML XML Plain text … Ako na to? triviálne, ale… znovupoužiteľnosť kódu prehľadnosť „sadnem si ku kódu za 2 roky“ builder.
Download
Report
Transcript Builder Builder - motivácia Motivácia sitemap v rôznych výstupoch HTML XML Plain text … Ako na to? triviálne, ale… znovupoužiteľnosť kódu prehľadnosť „sadnem si ku kódu za 2 roky“ builder.
Builder
Builder - motivácia
Motivácia
sitemap v rôznych výstupoch
HTML
XML
Plain text
…
Ako na to?
triviálne, ale…
znovupoužiteľnosť kódu
prehľadnosť
„sadnem si ku kódu za 2 roky“
builder
Builder
„Definícia“
vytvárací návrhový vzor (creational design pattern)
oddeľuje konštrukciu zložitých objektov od ich reprezentácie
Problém
máme rôzne zložité objekty s podobným postupom konštrukcie
sitemap v HTML, sitemap v XML, ...
Zámer
vytvoriť rovnakým postupom rôzne reprezentácie
systematicky vytvárať zložité objekty
zjednodušiť rozšíriteľnosť do budúcnosti
ešte sitemap v Plain text, ešte sitemap v UltraXYZ, ...
sprehľadniť zdrojový kód
skryť konkrétne implementačné detaily
že tam je presne <a href=... a <span style=“color: red“> nemusí nikto vedieť
Builder – schéma
Štruktúra
Časti
Director
Builder
definuje interface pre konštrukciu jednotlivých častí výsledného objektu
ConcreteBuilder
použije predhodený builder a po krokoch vytvorí objekt
implementuje interface Builder-u
definuje a skladuje vytvorenú reprezentáciu, na požiadanie ju vráti
Product
reprezentuje vytváraný objekt, prístup z ConreteBuilder-u
Builder - príklad
Príklad: Fast-food
vo fast-foode robia o. i. hamburgery
jednotný postup
žemľa, syr, omáčka, mäso, zelenina, ...
Direktor
nikto „neexperimentuje“
do hamburgerov sa dajú pridať iba vyššie spomenuté prísady
jednotné rozhranie
Builder
líšia sa v zložkách
„chickenburger“ - kuracie mäso, „cheeseburger“ – bez mäsa, viac syru, ...
ConcreteBuilder
hotový hamburger
Product
na požiadanie vydá ConcreteBuilder
ten, kto ho vyrobil
Builder – schéma volaní
Builder - implementácia
Builder
typicky abstraktná trieda
niekedy interface
virtuálne metódy
definujú, čo ma každý ConcreteBuilder vedieť
nie nutne „pure virtual“ metódy
dostatočne všeobecné rozhranie
nie nutne „void“
reimplementovať iba tie, ktoré mienime spracovávať z daného CBuilder-u
identifikácia vytvorených častí
poradie, náväznosť dielcov vedúcich k výslednému Product
Product
žiadna abstraktná trieda
nemalo by zmysel – zväčša sa dosť odlišujú
výzor produktu je daný konkrétnym ConcreteBuilder-om
Builder – príklad na UML diagramoch
Kód tvorby sa
nezaoberá konkrétnou
reprezentáciou
každému ConcreteBuilder-u prislúcha
reprezentácia výsledku
jednotné rozhranie
Builder – súvislosti, dôsledky
Štruktúra Produktu je viazaná na ConcreteBuilder
interface pre konštrukciu rovnaký
vnútorná štruktúra produktu schovaná
aj to, jak je presne zostavený (skryté konkrétne implementačné detaily)
zmena produktu = nový builder
Oddelenie konštrukcie od reprezentácie
modularita, zapuzdrenie (encapsulation)
Client nepotrebuje nič vedieť o triedach definujúcich Produkt (nie sú ani v rozhraní)
jeden Builder sa dá použiť pre rôzne Director-y
Director nevie presne o konkrétnej štruktúre Produktu
Umožňuje kontrolu konštrukcie za jej priebehu
konštrukcia produktu „step-by-step“ (riadi Director)
interface odráža proces konštrukcie produktu
Príklad Builder-u: Sitemap
Príklad Builder-u: Sitemap - Client
Požadovaný Builder
SiteMapBuilder builder = new XMLSiteMapBuilder();
SiteMapDirector director = new SiteMapDirector(builder);
director.Construct(webPageData);
Director dostane daný Builder
Necháme Director-a robiť svoju prácu
(nad zadanými dátami)
String siteMap = builder.GetSiteMap();
Sami z BUILDERU vyberieme výsledok
Príklad Builder-u: Sitemap - Director
public class SiteMapDirector {
SiteMapBuilder builder;
public void Construct(WebPageData data) {
try {
builder.BuildHeader();
siteMapBuilder.buildHeader();
for (int i = 0; i < data.webpages.length; i++) {
for (int i = 0; i < Data.webpages.length; i++) {
builder.BuildPage(new URL(data.webpages[i].getUrl()));
siteMapBuilder.buildPage(new YRL(Data.webpages[i].getUrl()));
}
}
builder.BuildFooter();
siteMapBuilder.buildFooter();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
Vlastná logika Director-u
Príklad Builder-u: Sitemap – XML builder
public class XMLSiteMapBuilder implements SiteMapBuilder {
private String siteMap;
public void BuildHeader() {
siteMap += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<urlset xmlns=\"...\">\n";
}
public void BuildPage(URL url) {
siteMap += "<url><loc>" + url.urlString + "</loc></url>";
}
public void BuildFooter() {
siteMap += "</urlset>\n</xml>\n";
}
public String GetSiteMap() {
return siteMap;
}
}
Príklad Builder-u: Sitemap – Text builder
public class TextSiteMapBuilder implements SiteMapBuilder {
private String siteMap;
public void BuildPage(URL url) {
siteMap += url.urlString + "\n";
}
public String GetSiteMap() {
return siteMap;
}
}
Príklad Builder-u 2 - motivácia
public class User
private final
private final
private final
private final
private final
}
chceme konštruktory s povinnými + všetky možné podmnožiny voliteľných argumentov
zásadne nechceme „setters“
konzistentný kód
viacvláknová aplikácia
jak vynútiť immutability...?
Riešenie 1: Použiť voliteľné argumenty
//required
//required
//optional
//optional
//optional
Konštruktory s voliteľnými argumentmi
{
String firstName;
String lastName;
int age;
String phone;
String address;
v Java, .NET staršom než 3.0, nejde!
Riešenie 2: Naprogramovať všetky možné konštruktory
...
Príklad Builder-u 2 – riešenie 2
public User(String firstName, String lastName)
this(firstName, lastName, 0);
}
public User(String firstName, String lastName,
this(firstName, lastName, age, "");
}
public User(String firstName, String lastName,
this(firstName, lastName, age, phone, "");
}
public User(String firstName, String lastName,
address) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.phone = phone;
this.address = address;
}
{
int age) {
int age, String phone) {
int age, String phone, String
// ... ešte treba ďalších 4 ...
// ... a čo zámena? „phone“ a „address“ sú rovnakého typu ...
Príklad Builder-u 2 – riešenie 3: Builder pattern
Riešenie 3: Použijeme Builder pattern
Jak?
Programátor, ktorý volí argumenty: Director
ConcreteBuilder: jediný argument konštruktoru triedy „User“
trieda „User“ si z ConcreteBuilder vytiahne Product
public class User
private final
private final
private final
private final
private final
{
String firstName;
String lastName;
int age;
String phone;
String address;
//
//
//
//
//
required
required
optional
optional
optional
// len 1 konštruktor s jediným argumentom: ConcreteBuilder
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
Príklad Builder-u 2 – riešenie 3: Builder pattern
public static class UserBuilder {
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder age(int age) {
this.age = age; return this;
}
public UserBuilder phone(String phone) {
this.phone = phone; return this;
}
public UserBuilder address(String address) {
this.address = address; return this;
}
public User build() {
return new User(this);
}
}
}
Príklad Builder-u 2 – riešenie 3: Builder pattern
User user = new User.UserBuilder("John", "Doe")
.age(30)
.phone("1234567")
.address("Fake address 1234")
.build();
Builder - zhrnutie
Kedy použiť Builder?
Algoritmus tvorby objektu nezávislý od konkrétnych „dielcov“
Treba viacero reprezentácií výsledku
dielce = typicky reprezentácia objektu
do budúcna
Konštruktory
Prečo ho použiť?
izolácia konštrukcie a reprezentácie
umožňuje zmeniť štruktúru bez prepisovania všetkých ConcreteBuilderov
nie je nutné presne vedieť, ako sa to poskladá
nasadenie v skupinách vývojárov
Builder – praktické príklady
Kde možno nájsť Builder, kde ho použiť
Častý pri konverziách
Vektorová grafika
GUI
SVG, Flash, konverzia do rastru
rovnaký obsah položiek
iné farby, tvar
Obsah podľa prihláseného užívateľa
jadro rovnaké
ďalšie položky zobrazené/vynechané podľa privilégií
Builder – súvisiace NV
Súvisiace návrhové vzory
Abstract Factory
dá sa chápať ako limitný prípad Builder-u
Builder vytvára objekty postupne, po častiach, vráti až na požiadanie
Produkty Builder-u nemusia implementovať spoločný interface
nasadenie Abstract Factory v prípade, že celý objekt je možné vytvoriť „jediným
volaním“
Composite
je často výsledkom práce Builder-u