top of page
Search
yuli0203

Design Patterns Overview

Updated: Feb 23, 2023

I view design patterns as some of the essential tools in the developer toolbox, in order to build software product. OOP principles and clean code are a good basis to start from, but they are not enough to solve some common software problems. The richer your toolbox is, the better you can choose the right tool for your specific task. Not only that, these tools are universal, and you have a very simple way to describe a complex problem and it's solution to your collogue using about two words.

Let's be honest, how many times did we solve a new software problem? Most of the problems we face are not new or unique. They re-appear across different projects across different industries, whether it's a life saving product or a game. Knowing to choose the right and easy solution right away will put you in an advantage, and will make your code much more maintainable in the future.


How do I learn Design Patterns?


Conventionally, there are 23 design patterns. There are many great books to read about the topic. I personally liked "Head First - Design Patterns" since it's narrative is kind of similar to my way of thinking. Knowing about design patterns does not necessarily mean knowing how to use them. When misusing them they can add to complexity without the benefits. The true art is knowing to fit the right solution to the right problem in the right amount.


An example of using design pattern instead of OOP


I will provide a very specific short example about what I meant.


Strategy Pattern - This is one of my favorite patterns that I found to be very useful. Many people, thinking of OOP, can say "Cat and Dog are Animal". That is intuitive and easy, but not always correct. Very often the modular part which you would need to reuse is the behavior/strategy, not the entity.

Let's imagine a game where you create some NPC animals to roam in the wild. At first the requirement is to add a fish that swims and a monkey that walks.


With classic inheritance our classes will look like this:

Each animal implements it's own movement.


With strategy pattern (the strategy is the movement), the implementation looks like this:


The second implementation did not care if the animal is fish or monkey, because what varies is the movement (in this simplified case). This pattern is based on composition instead of inheritance, and allowed extension using inversion of control. This will allow us much more flexibility. Let's receive the next requirements:


1) Add a Dolphin that swims.


The inheritance person will offer one of the following solutions: - "I can add a Dolphin class! But I need to implement the swim movement again..."

- "I know! The Dolphin is "sort of a fish" so I will inherit from Fish! Almost no code changed!"


The strategy person will not make any code changes and reuse the classes as is.


2) Add a main player that walks and jumps.


The inheritance person will offer the following solution: - "Human needs also to jump... So I can't reuse my classes since I support a single movement, maybe monkey? I need to implement a Human with walk and jump capabilities from the beginning."


The strategy person sees now that they need an object that supports multiple movement types. They add the Jump IMovement implementation, and afterwards designed a movement controller class, that supports multiple types of movement and their selection.


Conclusion


This was an extremely simple example, but it showed that the intuitive inheritance solution was not a good solution at all. When extending the classes, there was a choice between "copy pasting" between classes or forcing classes to reuse entities in a weird way, so there was no actual efficient reuse.

When we used strategy pattern, which is based on principles such as favoring composition over inheritance, and IOC we reused much more code and could continue development more naturally. Imagine if this was a much more complex feature. How many bugs would we have from copy pasting and forced reuse?


It is no easy task to select the right solution, which requires a lot of imagination to foresee the upcoming requirements. Decoupling our code properly can help us make it more modular and easy to maintain in the future. Design patterns already use some powerful more generic decoupling principles, as shown with the Strategy pattern. We can benefit greatly from using design patterns properly.


Recent Posts

See All

Comments


bottom of page