Lesson 4
Revising Basic Design Patterns: Composition in TypeScript
Lesson Overview and Goals

Hello, welcome back! Today, we will decode the fundamentals of Revising Basic Design Patterns - Composition! A vital component of software design patterns, Composition aids us in creating complex classes using simpler ones. With TypeScript, we have the added advantage of leveraging its powerful type system to ensure robust class structures. Our journey today includes understanding the concept of composition, its value in software development, and how to practically implement it in TypeScript.

Garnering Clarity on the Composition Design Pattern

To kick-start our exploration, let's understand Composition. In object-oriented programming (OOP), composition allows a class to include other classes, paving the way for the creation of complex systems out of simpler components. For instance, when building a car, we bring together independent pieces like the engine, wheels, and seats — a perfect reflection of composition in everyday life. Note that in composition, should the parent object (the car) be destroyed, the child objects (the components) also cease to exist.

Acing the Composition Design in TypeScript

Now, let's translate the theory into a TypeScript code application. Transforming the previously mentioned car example, a Car class in TypeScript is created by making objects of the Engine, Wheels, and Seats classes. The Car class owns these child objects; their existence is dependent on the Car.

TypeScript
1class Engine { 2 start(): void { 3 console.log("Engine starts"); // Engine start message 4 } 5 6 stop(): void { 7 console.log("Engine stops"); // Engine stop message 8 } 9} 10 11class Wheels { 12 rotate(): void { 13 console.log("Wheels rotate"); // Wheel rotation message 14 } 15} 16 17class Seats { 18 adjust(position: string): void { 19 console.log(`Seats adjusted to position ${position}`); // Seat adjustment message 20 } 21} 22 23class Car { 24 private engine: Engine; 25 private wheels: Wheels; 26 private seats: Seats; 27 28 constructor() { 29 this.engine = new Engine(); 30 this.wheels = new Wheels(); 31 this.seats = new Seats(); 32 } 33 34 start(): void { 35 this.engine.start(); // Call to start engine 36 this.seats.adjust('upright'); // Adjust seat position 37 this.wheels.rotate(); // Get wheels rolling 38 } 39} 40 41const myCar = new Car(); 42myCar.start(); // Begin car functions 43 44/* 45Prints: 46Engine starts 47Seats adjusted to position upright 48Wheels rotate 49*/

In the above code, the Car class encapsulates Engine, Wheels, and Seats objects, which are independent but part of the Car class, forming a Composition pattern.

Discerning Composition from Inheritance

In OOP, Composition and Inheritance are two significant ways to express relationships between classes. While Inheritance implies an "is-a" relationship, Composition suggests a "has-a" relationship. For instance, a Car IS A Vehicle (Inheritance), but a Car HAS an Engine (Composition).

Lesson Summary and Practice

Superb job! You've now decoded composition and even implemented it in TypeScript! Next, you'll encounter stimulating exercises where you'll gain hands-on experience with composition in TypeScript. Utilize TypeScript's static typing to ensure your class designs are robust and error-free. Stay curious, and keep practicing to fortify your concepts!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.