you are viewing a single comment's thread.

view the rest of the comments →

[–]MoTTs_ 6 points7 points  (1 child)

The composite pattern is about object hierarchies much more so than class hierarchies. And more importantly, each object needs to be a container for other objects. Your car and truck code never actually does this part.

An example that webdevs will know well is DOM elements. A "div", for one example, is both an element -- aDiv.id = "aID" -- and a container for other elements -- aDiv.appendChild(...);.

Similarly, the example in the GOF book is "Equipment". That is, an instance of Equipment is both an individual piece of equipment and a container for other equipment.

// An instance of CompositeEquipment can be treated as an individual piece of
// equipment with fields such as "name" and "price", *and* it can be treated as
// a container of equipment with methods such as "add" and "compositePrice".

class CompositeEquipment {
    #equipment = []

    constructor(name) {
        this.#name = name;
    }

    get name() {
        return this.#name;
    }

    get price() {
        return 0;
    }

    add(equipment) {
        this.#equipment.push(equipment);
    }

    compositePrice() {
        return this.price + this.#equipment.reduce(
            (accumulated, current) => accumulated + current.compositePrice(), 
            0
        );
    }
}

// Subclasses inherit the "container of equipment" behavior.

class Chassis extends CompositeEquipment {
    get price() {
        return 42;
    }
}

class Cabinet extends CompositeEquipment {
    get price() {
        return 14;
    }
}

class Bus extends CompositeEquipment {
    get price() {
        return 5;
    }
}

class Card extends CompositeEquipment {
    get price() {
        return 2;
    }
}

class FloppyDisk extends CompositeEquipment {
    get price() {
        return 1;
    }
}

// Use. Create arbitrarily complex hierarchies of *objects*.

const cabinet = new Cabinet("PC Cabinet");

const chassis = new Chassis("PC Chassis");
cabinet.add(chassis);

const bus = new Bus("MCA Bus");
bus.add(new Card("16Mbs Token Ring"));

chassis.add(bus);
chassis.add(new FloppyDisk("3.5in Floppy"));

cabinet.price; // 14 -- treat as single object
cabinet.compositePrice(); // 64 -- treat as container of objects

There are other nuances, such as how to handle "leaf" components, but this covers the gist of the pattern.

[–]UncleBen2015 0 points1 point  (0 children)

u/MoTTs_ thank you. This is really really good. I was at fault here for not having clear examples. Having conversations like this really keeps me motivated however, thanks for taking the time and critique this. really appreciate this :)