4. lépés - fluent builderes ablak

Tehát akkor:

public class Window extends JFrame {
    private static final long serialVersionUID = 1L;

    private Window(Builder builder) {
        setTitle(builder.text);
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static class Builder {
        private String text;

        public Builder text(String text) {
            this.text=text;
            return this;
        }

        public Window build() {
            return new Window(this);
        }
    }
}

Hm, nem is volt nehéz, igaz? Na jó, azért nem biztos, hogy elsőre így kezdtük volna - de már látszik, hogy előnyünkre lesz!

Ha további tulajdonságokat kell hozzátenni, akkor:

Az ablakot pedig a fluent builderrel könnyen összeépíthetjük, így:

public class WindowTest {
    public static void main(String[] args) {
        new Window.Builder()
        .text("Hello")
        .build();
    }
}

No most, miért nem

Window window=new Window.Builder()
.text("Hello")
.build();

Miért nem jegyezzük meg a legyártott Window példányt egy változóban? Azért nem, mert semmi szükségünk nincs rá. A legyártott ablak megjelenik a képernyőn - és eltűnik, ha bezárod. Mivel soha többet nem használjuk a programban, felesleges lenne egy változóba tenni, amit utána semmire nem használunk. Logikus? :)

Builder naming conventions

A 06-os részben sok szó esett a getterek és a setterek elnevezéséről. De milye van egy buildernek? Az biztos, hogy nem getterei, hiszen semmi értelmeset nem adnak vissza (csak a buildert magát a fluent interface kedvéért). Akkor ennek setterei lennének? Tulajdonképpen nem, mert valójában nem állít be még semmit - mert még nincs fagyi csak a build() meghívása után fog történni valami.

Sok elképzelés létezik, de a közmegegyezés az, hogy a builder egy deklaratív dolog, ezért a metódusainak a neve egyszerűen főnév. Tehát nem setText() hanem csak text(). Kivételt képeznek azok a metódusok, amik többszörösen hívva nem átírják a már létező értékeket, hanem hozzáteszik az új értéket, tehát addScoop() - ami hozzátesz egy gombócot, és nem pedig átírja a gombóc ízét.

Deklaratív programozás

A deklaratív szóval egyre többet fogunk találkozni. Ez röviden azt jelenti, hogy ahelyett, hogy részletesen a számítógépnek megparancsolnánk, hogy hogyan csináljon valamit, mi csak azt mondjuk meg, hogy mit csináljon. Ez az apró különbség valójában hatalmas, hiszen deklaratív módon sokkal rövidebben, és tisztábban fogalmazhatjuk meg a céljainkat. (Teljes programnyelvek vannak, amik kizárólag deklaratív módon programozhatók! A Java gyárilag egy buta imperatív nyelv, de miért is ne próbálnánk meg szebben, deklaratívabban használni?)

Imperatív: (azaz parancsoló, szóval nem-deklaratív)

Deklaratív: (azaz szándékainkat kinyilvánító)

Deklaratív GUI programozás

Amit most a fluent builderrel elértünk, az már erősen deklaratív érzés! Nézzük csak meg:

Imperatív: - sima Swing, szájbarágósan minden műveletet leírunk:

public static void main(String[] args) {
        JFrame frame=new JFrame(); // csinálj egy ablakot
        frame.setTitle("Hello"); // változtasd meg a szövegét 
        frame.pack(); // pakold össze - bármit is jelentsen ez
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // ezt is csináld
        frame.setVisible(true); // tedd láthatóvá
    }

Deklaratív: - a szándékainkat fejezzük ki, semmi mást nem írunk le:

public class WindowTest {
    public static void main(String[] args) {
        new Window.Builder() // legyen egy ablak
        .text("Hello") // legyen a felirata hello
        .build(); // csináld meg
    }
}

A különbség még szembetűnőbb lesz később, ahogy egyre több dolgot tud majd a saját kis mini-frameworkünk!

A deklaratív esetben sokkal kevesebb, sokkal logikusabb, sokkal kifejezőbb kódot írunk - és hagyjuk, hogy a framework amit csinálunk majd szájbarágja a részleteket a Swingnek, ami megcsinálja a tényleges melót.

A fluent builder

A fluent builderekekkel - bár egyszer meg kell őket írni - de utána nagyon könnyen és tisztán tudunk nagyon összetett GUI objektumokat készíteni.