Skip to main content

Example 2

// Bridge Implementation
// Define an interface for the Implementation

/**
* The Implementation defines the interface for all implementation classes. It
* doesn't have to match the Abstraction's interface. In fact, the two
* interfaces can be entirely different. Typically the Implementation interface
* provides only primitive operations, while the Abstraction defines higher-
* level operations based on those primitives.
*/
export default interface ColorInterface {
log(): string;
}
import ColorInterface from "./ColorInterface";

// Create a Concrete Implementation

/**
* Each Concrete Implementation corresponds to a specific platform and
* implements the Implementation interface using that platform's API.
*/
export default class BlueConcreteImplementation implements ColorInterface {
log() {
return "blue";
}
}
import ColorInterface from "./ColorInterface";

// Create a Concrete Implementation

/**
* Each Concrete Implementation corresponds to a specific platform and
* implements the Implementation interface using that platform's API.
*/
export default class RedConcreteImplementation implements ColorInterface {
log() {
return "red";
}
}
// Bridge Abstraction
import ColorInterface from "./ColorInterface";

// Define an abstract class for the Abstraction
/**
* The Abstraction defines the interface for the "control" part of the two class
* hierarchies. It maintains a reference to an object of the Implementation
* hierarchy and delegates all of the real work to this object.
*/
export default abstract class ShapeAbstract {
color: ColorInterface;

constructor(color: ColorInterface) {
this.color = color;
}

logMe() {
console.log(`I am a ${this.color.log()} shape.`);
}
}
import ShapeAbstract from "./ShapeAbstract";
import ColorInterface from "./ColorInterface";

// You can extend the Abstraction without changing the Implementation classes
export default class TriangleAbstraction extends ShapeAbstract {
constructor(color: ColorInterface) {
super(color);
}
}
import ShapeAbstract from "./ShapeAbstract";
import ColorInterface from "./ColorInterface";

// You can extend the Abstraction without changing the Implementation classes
export default class CircleRefinedAbstraction extends ShapeAbstract {
constructor(color: ColorInterface) {
super(color);
}

// Create a refined Abstraction that behaves slightly differently
logMe() {
console.log(`I am a ${this.color.log()} circle.`);
}
}
import CircleRefinedAbstraction from "./CircleRefinedAbstraction";
import TriangleAbstraction from "./TriangleAbstraction";
import RedConcreteImplementation from "./RedConcreteImplementation";
import BlueConcreteImplementation from "./BlueConcreteImplementation";

// Bridge pattern is to link the abstraction and implementation which had been separated
// Instantiate the circle with a concrete implementation

/**
* The client code should be able to work with any pre-configured abstraction-
* implementation combination.
*/
const circle = new CircleRefinedAbstraction(new RedConcreteImplementation());
const triangle = new TriangleAbstraction(new BlueConcreteImplementation());

circle.logMe(); // Output: I am a red circle.

triangle.logMe(); // Output: I am a blue shape.