I present to you the design patterns…
Haz clic para leer esta publicación en español.
Design patterns are like specialized tools that are tried and tested, ready to solve those problems that often arise repeatedly during software development. It's like having a set of proven techniques that allow you to effectively tackle common challenges in the development cycle.
A little context...
In my personal experience, as I taught myself programming, I reached a point where I felt stuck. Despite having basic knowledge of programming languages and understanding concepts like statements and object-oriented programming, I encountered a dilemma: my programs, although they worked, were not well-designed for scalability. What initially seemed simple soon became a challenge to maintain and develop further as it grew in complexity.
I was in search of a more professional way to develop applications, but I found myself lost not knowing where to start. Fortunately, life introduced me to friends with vast experience in the field. They suggested I research Design Patterns, especially the book by the famous group known as the "Gang Of Four," four developers who in 1994 published a book titled "Design Patterns: Elements of Reusable Object-Oriented Software." It was through this reading that I began to understand the fundamentals of application architecture, only scratching the surface of all that I still had to discover in this fascinating world of programming.
What can I achieve using design patterns?
What you can achieve without patterns is essentially the same, but the big difference lies in having an application that won't require rebuilding from scratch as it begins to expand. Additionally, you'll have standardization in the solution's namespace, which helps you remember what you were thinking when writing that piece of code.
Types of design patterns
Design patterns are classified into various types, which are linked to the types of problems they solve. There are three main categories: object creation, object composition, and object behavior. An important tip about patterns is, "If you have a hammer, not everything is a nail," which means not all design patterns apply to all programs, and there definitely isn't a "Best Pattern." Each pattern or combination has its pros and cons. Now, let's make a brief list of the patterns in each category.
Structural Patterns
Structural Patterns tell us how classes relate to each other to form larger structures. This helps us solve problems in a more organized and efficient way.
Adapter
The Adapter pattern solves the issue of connecting two different interfaces by converting data so they can be transmitted between them. It's like using an electrical adapter to switch from a two-prong plug to a three-prong one. It's like when you buy a device from overseas and need to use it here in Argentina, but the plugs are different. With the adapter, you make everything fit and work smoothly.
Adapter
Bridge
The Bridge pattern gives us the chance to separate an abstract idea from how it's actually carried out.
What does that mean? Well, the client has no clue how things are done underneath, they just know they have to call a certain method and that's it. This is really useful because it allows us to change how things are implemented while the program is running, without the client even noticing.
So, we achieve a really cool decoupling and it gives us the freedom to change things without affecting the rest of the code.
Composite
The Composite pattern is like building something big with smaller pieces, like those puzzles that make you want to throw everything out the window.
Imagine a family tree, remember those? Well, it's something like that but in code. For example, think of a game like World of Warcraft, where you have a whole 3D world to explore. Each part of the game, like characters, enemies, or landscapes, can be represented as an object itself, but at the same time, all together they are part of something much bigger. It's like building a giant Lego with a bunch of smaller pieces, but in the end, you get something cool.
On the map, you can see there are lots of trees, you see? All those little trees are like 3D models that the game loads. And you know what? Many of them are more alike than two drops of water. But together, they form all that green you see in the game, like a real forest, but in the virtual world.
Decorator
Look, to give you a clearer idea, let's think of a video game character, let's say it's an archer. Well, you know, archers use their bows to attack and each bow has its power. Now, how do we make our character change bows without complicating our lives or without making a code that looks like a maze?
This is where the Decorator pattern comes into play. This pattern allows us to add or remove skills while the game is running. So, our archer can use bows that seem to come from a fairy tale, without making the game slower or the code a mess. It's like having the best of both worlds: customization without breaking everything.
Facade
Now I'm going to explain something that will surely help you understand better how some things work in programming. Have you ever thought about how the engine of a car works inside? Well, imagine having to understand and manage every piece, every cable, every part that makes the engine work. It would be a mess, right?
Well, in programming, something similar happens sometimes. There are times when we deal with a bunch of methods and functions, and knowing the exact order in which they need to be called can be a headache. This is where the Facade pattern comes into play. This pattern simplifies our lives, it gives us a kind of easy-to-use "window" to interact with all those "engine" of complicated functions. It's like having a remote control for the car, all in one button. A marvel!
Flyweight
When you have many objects with similar functions, sometimes it's better to group those functions into a single external entity. Why? Because that allows you to save memory and make your code more efficient.
Instead of having a thousand objects with similar methods taking up space, you can have just one that shares those functionalities. So, you free up memory and make your program lighter.
Like putting all your tools in a box, instead of having them scattered all over the house. More order, less mess!
Private Class Data
The Private Class Data pattern allows us to protect certain attributes of an object, preventing curious or distracted hands from manipulating them, especially when we can't define them as constants or final.
Imagine you're designing a panel to create a character in a game. You have to assign strength, agility, intelligence, and stamina points, which will be vital for its development throughout the game. Once the character is created, these attributes are crucial, as they directly affect its performance in battles and missions. That's why it's essential to protect them from external modifications that could ruin the gaming experience.
Proxy
The Proxy pattern is used when we use one object to represent another, and although it may seem useless at first, it is very useful in certain circumstances. A real-life example of the Proxy pattern is a debit card.
The debit card manages account balances that reflect the available cash balance in the bank. If you need to use those funds in real life, you can go to the bank and withdraw them in person, but that involves a greater cost of time and effort than simply using them through the card.
Creational Patterns
This type of pattern is responsible for controlling how objects are created and instantiated, thus freeing other classes in the system from that responsibility.
It's like when a magician summons elementals: no one cares how they're actually summoned, we just want to use them to fight.
Abstract Factory
The Abstract Factory pattern helps us create an instance belonging to a family. For example, let's take the case of the character creator panel, we have races, Elf, Gnome, and Human. Each race needs a body, but it wouldn't be possible to assign a Human body to a Gnome. In these cases, the Abstract Factory pattern helps us at the moment of instantiating a Player to pass it to which family of components it belongs and our Gnome can start on the right foot and have its head, body, and initial weapons according to its race.
Builder
The Builder pattern allows us to delegate the creation of complex objects to another class.
For example, if we need to create a Dragon Slayer Fire Sword and another Dragon Slayer Ice Sword, both swords need different components to be created. Then, we need something that assembles them and gives us our Sword. These are the parts of our Builder pattern.
Factory Method
This pattern also serves us to delegate the creation of an object to another class, but it's simpler. The Factory Method tells a Factory Creator what object it wants, without knowing how it's created, which benefits decoupling.
Object Pool
The Object Pool pattern helps when we need to optimize resources. If we have an object costly in resources to be instantiated and we need it temporarily, like a spell casting animation, this pattern has a warehouse of instances that can be called and then become available again for another task.
Prototype
The Prototype pattern establishes a model object from which copies are generated at runtime, like the clones in Naruto, which are exactly the same as the original, even in their state.
Singleton
The Singleton pattern ensures that there is only one instance of a class in the system. For example, we can create an NPC king of the city and be sure that there will never be another while that king remains alive.
Behavioral Patterns
These patterns are oriented towards communication between classes, responsibility assignment, and collaboration between objects.
Chain of responsibility
This pattern helps when processing is sequential, like in a production line, where the product is processed in a series of stages until it reaches the desired state.
Command
This pattern helps us invoke routines or subprograms without really knowing what they do, like water elementals in a game, which fight for us without needing to understand how they do it.
Interpreter
This pattern deals with expressions or statements that need to be evaluated, like understanding keywords that a player types or recognizing a strange language like Elvish.
Iterator
Iterator helps to traverse a list or collection of objects without needing to know how the collection is implemented, just by calling certain methods previously established.
Mediator
This pattern creates a mediator between objects, like in a chat system, where a message is communicated to all participants in the room.
Memento
Memento allows saving and restoring the state of an object at a given moment, like saving the state of an online RPG game to be able to return to a previous point. For example, every half hour, a complete backup of the maps with the players' locations, items, and more can be made. In case something happens to the current state of the game, we can return to the last saved state.
Null Object
It avoids errors when referencing a null dependency, creating objects without behavior that prevents the program from crashing.
Observer
It allows "observers" to receive updates from an "emitter" when its state changes. Like when the "emitter" makes a change, all subscribers receive a message with the update.
State
The State design pattern is used when an object has different behaviors depending on its state, like a spell that can be active or inactive.
Strategy
Strategy Delegates the execution of a method to concrete classes, allowing the behavior of the method to be changed at runtime.
Template Method
Reduces duplicate code by establishing an abstract class with shared base behaviors for all child classes.
Visitor
The Visitor pattern adds functionalities to a class without modifying it, useful for adding features like weapons to a character without modifying its base class.
Conclusion
Design Patterns are powerful tools that can either help or hinder depending on how they are used. This introduction is just a glimpse; you can explore links to learn more details and examples.
See you in the next post.
< The last one turns off the light >