Design Patterns

i Java

Et lite forbehold:

Nøyaktig hva som er et Design Pattern og hva som bare er en måte å gjøre ting på, og hvorvidt forskjellige ting faktisk er bruk av et Design Pattern kan diskuteres mer enn hva som er fornuftig.

 

Jeg sier garantert noe andre vil si er feil, men poenget er generelle konsepter, ikke detaljene.

Iterator

En måte å gå igjennom elementer i en samling uten å eksponere den underliggende representasjonen.

 

Man har et eget objekt (iteratoren) som håndterer det å finne neste element, og å avgjøre om det er flere elementer igjen.

Hvorfor er dette nyttig?

At vi har blitt kjent med hva en Iterator er gjør at vi kan snakke om en Iterator som et konsept, i stedet for å snakke om et objekt som har en metode next() og hasNext(), har tilstand osv...

Det gjør også at dersom vi ser en Iterator i en annet språk skjønner vi hva det er. Eller dersom det heter noe annet og noen sier "det er en Iterator" kan det gjerne være forklaring nok.

Factory methods

En metode som returnerer et (nytt?) objekt, mye på samme måte som en konstruktør.

 

Så hvorfor ikke bare en konstruktør? En konstruktør må gi en ny instans av klassen selv. En Factory Method kan returnere instanser av en annen klasse (f.eks. en underklasse eller en skjult klasse) eller resirkulere objekter.

Factory Method

public class Car {
    public static Car withSpeed(int speed) {
        if (speed > 200) return new SportsCar();
        if (speed < 50) return new Lada();
        return new Car();
    }
}

class SportsCar extends Car {}

class Lada extends Car {}
Car myCar = Car.withSpeed(250);

Abstract Factory

public interface GuiFactory {
    public Window createWindow();

    public Button createButton();
}

public class GuiFactories {
    private GuiFactory() {}

    public static GuiFactory getByOs() {
        String osName = System.getProperty("os.name");
        if (osName.startsWith("Windows")) {
            return new WindowsGuiFactory();
        }
        if (osName.startsWith("Mac")) {
            return new MacGuiFactory();
        }
        if (osName.startsWith("Linux")) {
            return new LinuxGuiFactory();
        }
        throw new RuntimeException("Incompatible OS");
    }
}

Singleton

En klasse det bare skal finnes ett objekt av

public class SingleThreadSingleton {
    private static SingleThreadSingleton instance;

    private SingleThreadSingleton() {
        // We don't let others create an instance
    }

    public static SingleThreadSingleton getInstance() {
        if (instance == null) {
            instance = new SingleThreadSingleton();
        }
        return instance;
    }
}
public class ThreadSafeSingleton {
    private static class Holder {
        static final ThreadSafeSingleton instance = 
                new ThreadSafeSingleton();
    }

    private ThreadSafeSingleton() {
        // We don't let others create an instance
    }

    public static ThreadSafeSingleton getInstance() {
        return Holder.instance;
    }
}

Builder

En egen klasse for å lage objekter av en annen klasse.

 

For eksempel for å unngå en konstruktør med veldig mange parametere. Eller fordi det å lage en instans og så modifisere den enten ikke er mulig eller er for "dyrt".

Locale locale = new Locale.Builder()
    .setLanguage("sr")
    .setScript("Latn")
    .setRegion("RS")
    .build();
String s = count + " bottles of " + beverage + " on the wall";

String s = new StringBuilder(32)
    .append(count)
    .append(" bottles of ")
    .append(beverage)
    .append(" on the wall")
    .toString();

Hver gang man legger til noe på en String i Java lages det et nytt String-objekt, som også vil si en ny char[] på innsiden.

 

Så for å bygge opp en lang String med f.eks. en løkke, kan man bruke StringBuilder for bedre ytelse. Java gjør noen konverteringer av typen under automatisk når du kompilerer:

StringBuilder

Strategy

En måte å få algoritmer til å endre oppførsel ved kjøring.

 

List.sort(Comparator)

Observer

En måte å holde mange objekter oppdatert på endringer i et annet.

Decorator

En måte å endre funksjonaliteten til en annen klasse uten å endre hverken koden dens, eller hvor den kan brukes.

interface Car {
    void start();
    void turnLeft();
    void turnRight();
    void stop();
}

class CarLogger implements Car {
    Car decorated;

    public CarLogger(Car decorated) {
        this.decorated = decorated;
    }

    void start() {
        log("starting");
        decorated.start();
    }

    void turnLeft() {
        log("turning left");
        decorated.turnLeft();
    }

    void turnRight() {
        log("turning right");
        decorated.turnRight();
    }

    void stop() {
        log("stopping");
        decorated.stop();
    }
}
Car loggedCar = new CarLogger(otherCar);
class ReverseComparator<T> implements Comparator<T> {
    final Comparator<T> cmp;

    ReverseComparator(Comparator<T> cmp) {
        this.cmp = cmp;
    }

    public int compare(T t1, T t2) {
        return cmp.compare(t2, t1);
    }
}

Tatt fra Collections.reverseOrder:

Kode fra presentasjonen:

https://github.com/evestera/1010-pusle

Design Patterns​ i Java

By Erik Vesteraas

Design Patterns​ i Java

  • 1,172