Zachary W. Huang
Idea: Decoupling an abstraction from its implementation makes it easy to change behavior, the “backend” layer, etc, by simply swapping out concrete implementations. This is more flexible than simply subclassing an abstraction once for each implementation/platform.
Notice that even subclasses of an abstraction generalize well to any implementation as long they don’t use any implementation-specific behavior (i.e. calling abstract methods like this.doThing()
instead of reaching directly into this.imp
).
class Abstraction {
imp: Implementation;
constructor(imp: Implementation) {
this.imp = imp;
}
doThing() {
// forward to a concrete implementation
this.imp.doThing();
};
}
class RefinedAbstraction extends Abstraction {
doSpecialThing() {
this.doThing();
this.doThing();
this.doThing();
};
}
class Implementation {
doThing() {};
}
class ImplementationA extends Implementation {
doThing() {
console.log("A");
};
}
class ImplementationB extends Implementation {
doThing() {
console.log("B");
};
}
function main() {
const object = new RefinedAbstraction(new ImplementationA());
object.doSpecialThing(); // "A"
}