DEV Community

LP
LP

Posted on

OOP Simplified: Quick Factory Methods with Encapsulation, Abstraction, and Polymorphism in TypeScript

This article explores the Factory Method design pattern in TypeScript, highlighting how it uses object-oriented programming (OOP) principles: encapsulation, abstraction, and polymorphism.

Currently I am deepening my understanding of design patterns by studying the catalog from Refactoring Guru. In this article, we'll explore how to create smart home devices using the Factory Method pattern, illustrating how this approach can lead to more flexible and maintainable code.

Follow along as I post an article for each design pattern, documenting my learning journey and sharing practical examples.

The Factory Method Pattern

The Factory Method pattern is a design that defines an interface for creating objects while allowing subclasses to decide which classes to instantiate. TypeScript’s powerful type-checking and higher-order functions make it an excellent choice for implementing this pattern, resulting in robust and maintainable code.

Example: Smart Home Device Factory

Imagine a smart home ecosystem. We'll create a factory function to generate objects for various smart home devices, all adhering to a unified interface.

Defining the Interface

The SmartDevice interface ensures that all smart devices have an operate method.

interface SmartDevice {
  operate: () => string;
}
Enter fullscreen mode Exit fullscreen mode

Creating Factory Functions

Here's how createLight and createThermostat functions produce objects conforming to the SmartDevice interface.

const createLight = (): SmartDevice => {
  return {
    operate: () => 'Turning on the light',
  };
};

const createThermostat = (): SmartDevice => {
  return {
    operate: () => 'Adjusting the thermostat',
  };
};
Enter fullscreen mode Exit fullscreen mode

Higher-Order Factory Function

The getDeviceFactory function returns the appropriate factory function based on the DeviceType.

type DeviceType = 'light' | 'thermostat';

const getDeviceFactory = (type: DeviceType): (() => SmartDevice) => {
  switch (type) {
    case 'light':
      return createLight;
    case 'thermostat':
      return createThermostat;
    default:
      throw new Error("Unsupported device type");
  }
};
Enter fullscreen mode Exit fullscreen mode

Instantiating Devices

Factory functions from getDeviceFactory are used to create new smart device objects.

const lightFactory = getDeviceFactory('light');
const thermostatFactory = getDeviceFactory('thermostat');

const myLight = lightFactory();
const myThermostat = thermostatFactory();

console.log(myLight.operate()); // Outputs: Turning on the light
console.log(myThermostat.operate()); // Outputs: Adjusting the thermostat
Enter fullscreen mode Exit fullscreen mode

OOP Principles Illustrated

Encapsulation

Encapsulation is demonstrated by how the factory functions createLight and createThermostat manage the creation details of SmartDevice objects. The internal logic is hidden within each factory function, simplifying client interaction.

Abstraction

Abstraction is applied through the SmartDevice interface and the higher-order factory function getDeviceFactory. The interface defines a consistent contract for smart devices, and the factory function abstracts the creation process, making it easy to extend and modify.

Polymorphism

Polymorphism is demonstrated by handling different types of smart devices (lights and thermostats) through a single interface (SmartDevice). This consistent interface enables seamless method invocation (operate) across various device types, allowing for flexible and interchangeable usage of the smart devices.

Conclusion

The Factory Method pattern highlights the power of OOP principles in creating flexible and maintainable code. Encapsulation, abstraction, and polymorphism work together to enhance system robustness, making it easier to manage and extend.

By applying these principles and patterns in your TypeScript projects, you can build scalable, efficient software systems that are easier to understand and maintain.

Top comments (0)