Three Design patterns you're probably already using

Becca Nelson

March 16, 2017

 

Strategy pattern

decorator pattern

factory pattern

 

Calculate Revenue

Fetch exchange rates from API

User inputs exchange rate

What if we used dependency injection to inject the algorithm into the model?

Strategy pattern

function makeMusic(instrument: string): void {
    if (instrument === "piano") {
        console.log("Now playing: Mozart's Theme and Variations on Twinkle Twinkle Little Star");
    } else if (instrument === "clarinet") {
        console.log("Squeeeeak!!");
    }
}

makeMusic("piano");
// => Now playing: Mozart's Theme and Variations on Twinkle Twinkle Little Star

makeMusic("clarinet");
// => Squeeeeak!!

What if I wanted to add another instrument?

Here's a better way...

interface InstrumentStrategy {
    play();
}

class Drum implements InstrumentStrategy {
    play() {
        console.log("Thump.");
    }
}

function makeMusic(instrument: InstrumentStrategy) {
    instrument.play();
}

makeMusic(new Drum());
//=> Thump.

Notice how the makeMusic function never has to change.

Dependency inversion principle

one should "depend on abstractions, '[not] concretions".

const song = new Slow_Minor_Classical_Variation("Twinkle Twinkle Little Star");

Decorator pattern

BufferedReader fileReader = 
    new BufferedReader(
        new FileReader(
            new File("some.file")));

Decorator pattern (cont)

interface Song {
    play(title: string): void;
}

class Theme implements Song {
    play(title: string): void {
        console.log(`Now playing "${title}"`);
    }
}

const song = new Theme();
song.play("Twinkle Twinkle Little Star");
//=> Now playing "Twinkle Twinkle Little Star"

Interface

Base Class

Decorator pattern (cont)

class Variation implements Song {
    constructor(protected song: Song) { }
    
    play(title: string): void {
      this.song.play(title);
    }
}

class Minor extends Variation {
    play(title: string): void {
        title = `a minor variation on ${title}`;
        this.song.play(title);
    }
}

const song = new Minor(new Theme());

Decorator base

Decorators

“software entities … should be open for extension, but closed for modification.”

Open/closed principle

Factory Pattern

options

factory

instance

Factory Pattern (cont)

class MusicFactory {
    theme: Theme = new Theme();

    composeVariation(params: SongParams) {
        if (params.key === "minor") {
            this.theme = new Minor(this.theme);
        }
        if (params.style === "classical") {
            this.theme = new Classical(this.theme);
        }
        // etc.
        return this.theme;
    }
}

becca@8thlight.com

@beccaliz

Contact Me

Three Design Patterns You're Probably Already Using

By Becca Nelson

Three Design Patterns You're Probably Already Using

  • 974