Skip to content

Instantly share code, notes, and snippets.

@tatarianBarbarian
Last active March 3, 2023 13:34
Show Gist options
  • Save tatarianBarbarian/8765ca83155cfcbc50d6aefec2795fb3 to your computer and use it in GitHub Desktop.
Save tatarianBarbarian/8765ca83155cfcbc50d6aefec2795fb3 to your computer and use it in GitHub Desktop.
I asked ChatGPT to explain me Abstract Factory pattern

Can you explain me abstract factory pattern? Use javascript and ascii illustrations.


Sure, I'd be happy to explain the abstract factory pattern!

The abstract factory pattern is a design pattern that provides an interface for creating families of related objects without specifying their concrete classes. This pattern is useful when you want to create different types of objects that belong to a specific family, but you don't want to tightly couple your code to those specific types.

Here's an example implementation of the abstract factory pattern in JavaScript:

// Abstract factory interface
class ShapeFactory {
  createRectangle() {}
  createCircle() {}
}

// Concrete factory 1
class SimpleShapeFactory extends ShapeFactory {
  createRectangle() {
    return new SimpleRectangle();
  }

  createCircle() {
    return new SimpleCircle();
  }
}

// Concrete factory 2
class FancyShapeFactory extends ShapeFactory {
  createRectangle() {
    return new FancyRectangle();
  }

  createCircle() {
    return new FancyCircle();
  }
}

// Abstract product interface
class Shape {
  draw() {}
}

// Concrete product 1
class SimpleRectangle extends Shape {
  draw() {
    console.log('Drawing a simple rectangle');
  }
}

// Concrete product 2
class SimpleCircle extends Shape {
  draw() {
    console.log('Drawing a simple circle');
  }
}

// Concrete product 3
class FancyRectangle extends Shape {
  draw() {
    console.log('Drawing a fancy rectangle');
  }
}

// Concrete product 4
class FancyCircle extends Shape {
  draw() {
    console.log('Drawing a fancy circle');
  }
}

// Client code
function drawShapes(factory) {
  const rectangle = factory.createRectangle();
  const circle = factory.createCircle();

  rectangle.draw();
  circle.draw();
}

const simpleFactory = new SimpleShapeFactory();
const fancyFactory = new FancyShapeFactory();

drawShapes(simpleFactory);
drawShapes(fancyFactory);

In this example, we have an abstract ShapeFactory interface that defines methods for creating different types of shapes. We then have two concrete implementations of the factory: SimpleShapeFactory and FancyShapeFactory. Each of these factories knows how to create different types of shapes.

We also have an abstract Shape interface that defines a draw method. We then have four concrete implementations of the shape interface: SimpleRectangle, SimpleCircle, FancyRectangle, and FancyCircle. Each of these shapes knows how to draw itself in a different way.

Finally, we have a drawShapes function that takes a factory as its argument and uses that factory to create a rectangle and a circle. It then calls the draw method on each of those shapes.

Here's an ASCII illustration of how this all fits together:

            +-----------+
            | Shape     |
            |  draw()   |
            +-----------+
                  ^
                  |
         +-----------------+
         |                 |
  +--------------+  +--------------+
  | SimpleShape  |  | FancyShape   |
  |  createRect()|  |  createRect()|
  |  createCirc()|  |  createCirc()|
  +--------------+  +--------------+
                  ^       ^
                  |       |
        +--------------------------+
        |                          |
+------------------+   +------------------+
| SimpleRectangle  |   | FancyRectangle   |
|    draw()        |   |    draw()        |
+------------------+   +------------------+
| SimpleCircle     |   | FancyCircle      |
|    draw()        |   |    draw()        |
+------------------+   +------------------+


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment