A design pattern in the software engineering world is a reusable solution to a common problem in the software design. You can think of design pattern as a template for solving a problem, not as a finished design that can be converted to the source code. It all comes from Gang of Four book Design Patterns: Elements of Reusable Object-Oriented Software. Name Gang of Four refers to the four authors of the book Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides (hence Gang of Four). GOF book describes elegant and very simple solutions to specific problems in object-oriented software design. It's twenty-four years after the publication of the book but still, it remains incredibly relevant. In the preface of the book is stated that this book isn't an introduction to object-oriented technology or design but it assumes that you are reasonably proficient in at least one object-oriented programming language. And also that it isn't an advanced technical treatise but a book of design patterns that offers elegant and simple solutions to the problems in the object-oriented world.
In the next few chapters(articles) we will cover three basic kinds of design patterns:
All of the examples will be written in python but they apply to other object-oriented languages as well since design patterns are language neutral. Nowadays some design patterns are so common that they're now built into most modern languages.
Creational design patterns in software engineering world, are design patterns that are responsible for an efficient way of creating objects. This type of patterns adds simplicity to object creation by controlling it. Creational design patterns further can be categorized into Class and Object creational patterns, where Object-creational deal with Object creation and Class-creational deal with class instantiation. We will make an overview of six well-known creational design patterns:
- Factory Method
- Abstract Factory
- Object Pool
The Factory Method pattern use factory methods for creating objects without specifying the class of the created object. The main idea of the Factory Method is to define an interface for creating objects and let the subclasses to decide which class they will instantiate.
The Factory Method pattern, the way it's implemented here, is slightly different from the factory method in a typical programming language because we are trying to fully take advantage of all the features of Python. In this example get_vehicle function will return Car or Bus object, depending on the provided name. In the future, if a new type of Vehicle needs to be added to the factory method it will be very easy.
This design pattern usually is called the factory of factories because it provides an interface for creating a factory of dependent objects.
In this example, VehicleStore encapsulates object creation, and delegates object creation to factory objects instead of creating them directly. Following the example you can see that buy_vehicle calls CarFactory and return new Car, so adding new Factory such as Bus or Tram concrete factory is not a big problem.
You can use Singleton as design pattern when you'd like to allow only one object to be instantiated from a class. As a Python example, we will use a Borg pattern which is a one way to implement singleton behavior in Python. One important thing to note is that in python all instance attributes are stored in a dictionary called __dict__. Each instance will have own dictionary, so Borg pattern modifies that so all instances can share the same dictionary. That said, you could create as many objects as you want but they will share same state information so we can achieve Singleton behavior.
Even if obj1 and obj2 are different instances they share the same attribute name which value will be Obj2. In Python 3 you can use metaclass syntax to achieve Singleton class, example:
In this case, we will have only one instance from obj1 and obj2(check id), and provide a global point of access to it.
From the two examples, we can notice the main difference is the fact that creating Singleton will always return the same instance, opposite of Borg pattern which will return a new object (but it will share all fields).
This design pattern separates the construction of complex objects so that the same process can create different representations. The main problem that Builder design pattern solves is that it simplifies the creation of complex objects.
Product class defines the complex object that needs to be created by the builder.
Abstract builder class defines each of the steps that need to be done to create the product. Those steps are abstract since the functionality is carried to subclasses.
ConcreteBuilder class extends Builder and is responsible for the creation of the complex product.
Director controls the flow for generating the final product object. Its constructor is called and calls the specific concrete builder to generate the product.
Sometimes the cost of creating new objects is expensive and resource intensive. Cloning the objects, in that case, will be a great idea. The prototype design pattern is the one that does that. Instead of creating a new instance it copies an existing object.
In this example the PrototypeDispatcher allows clients to query it for a prototype before cloning new instance. This is very useful because it makes easier to derive new objects when instances of the class have a few different combinations of state.
The Object Pool design pattern uses a pool of initialized objects that are ready to be used rather than creating a new object all the time. The main idea of an Object Pool is that instead of creating instances of the class you can reuse them by getting them from the pool.
The Pool class is responsible for acquiring and releasing objects from the pool. In the initialize method it accepts the size parameter for creating a number of objects in the pool. This design pattern is effective in situations where the cost of creating objects is expensive and you need only a few of them.
Use case of Creational Design Patterns
Very often software engineers start out using Factory Method since it is easily customizable and not complicated, but it can evolve toward Builder or Abstract factory as more complex and flexible. Abstract Factory classes can be implemented using Prototype or Factory Methods. Also, Builder, Prototype or Abstract Factory can use Singleton in their implementation. That's why we can say that most of the creational design patterns could be competitors or they could be complementary between them self.
For further information Check Introduction to Structural Design Patterns.