top of page

Design patterns


If you are reading this article there is a big chance you've already encountered situations were you as a software developer were facing the same problem over and over again in the same environment and you usually replicated the solution in each case, and you know deep inside that it's something wrong about it and it's definetly not an elegant piece of code. That is where design patterns come in handy. This article is intended as an introductory into design patterns. The actual implementation details of each pattern will be treated in separate articles.

Better understanding of design patterns

When it is said that design patterns address problems as a generic solution, it is actually a bit more specific than that, in the ideea that each pattern addresses a very specific problem and is usually related to a specific category of problems, and they are divided into several categories such as:

  • creational patterns

  • structural patterns

  • behavioral patterns

  • concurrency patterns

Classification of design patterns

Creational patterns

Creational patterns address the issue of how objects are actually created and it usually decouples functionality from the creation of it's objects and delegates some other component to do that. This is usefull when you don't want to think too much about how your objects are created or if you don't need a great degree of control over instantiation each time you have to create something. Most common creational patterns are:

  • Singleton - limits you to single class instantiation

  • Factory - hides instantiation logic and provides you with a new instance based on the type of instance that you want

  • Factory method - forces subclasses to decide how to instantiate an object

  • Abstract factory - handles instantiation for family of realted objects without specifying the actual class

  • Builder - creates an instance step-by-step and returns it only when it is required

  • Prototype - provides means of cloning an object

  • Object pool - shares reusable objects that are expensive to create between components of an application

Structural patterns

This category of patterns is about the way that entities/objects interface and relate to one another in a software application. Most common structural patterns are:

  • Adapter - provides a way of interfacing calls between two components that are incompatible in interface

  • Aggregate - encompass multiple similar objects into one

  • Bridge - decouples implementation and abstractization and lets them vary easily

  • Composite - composes objects into tree structures representing part-whole hierarchies

  • Decorator - adds extra responsability dinamically to any component

  • Extensibility - hides complexity between simple interface

  • Facade - simplifies an existing interface

  • Flyweight - uses shared objects into multiple contexts simultaneously to avoid great costs

  • Pipes and filters - the outputs of some objects become the inputs of other objects in a pipeline fashion

  • Private class data - encapsulate class data and their manipulation

  • Proxy - provides a placeholder for an object

Behavioral patterns

As the name suggests, it's all about how components of an application behave one in relation to another. Most common behavioral patterns are:

  • Chain of responsability - decouple senders of a request from the receivers giving multiple object a chance to handle that request

  • Command - encapsulates a request as an object

  • Iterator - provides a way to access elements of an aggregate object without exposing it's internals

  • Mediator - provides loose coupling in the interaction between two objects

  • Memento - keeps the state of an object in a separate object and provides a way to restore that state

  • Null object - use of a default object

  • Observer - implements a one-to-many dependency relation where one object's state change affects many other objects

  • Protocol stack - encapsulate hierarchy consisting of several layers of communication

  • Scheduled-task - delay and expect a task to be executed at a specific point in time

  • Single-serving visitor - optimisation of the visitor pattern by carefully allocating/deallocating the visitor object

  • Specification - recombination of business rules using boolean logic

  • State - an object changes it's behaviour based on the state it currently has

  • Strategy - a pack of algorithms that are interchangeable based on the situation they are used in

  • Template method - enables subclasses to alter parts of an algorithm that is defined as a skeleton in the base class

  • Visitor - separate algorithm from data

Concurrency patterns

Addresses problems related to the multi-threaded type of applications. Most common concurrency patterns:

  • Active object - the body of a function is executed on a separate thread

  • Balking - ignore execution until an object has a particular state

  • Barrier - synchronization method in which a group of threads must reach a certain point in order for a another thread to continue it's execution

  • Double-checked locking - precheck the aquisition of a lock in an unsafe manner in order to reduce overhead

  • Event-based asynchronous - prevents thread from blocking while waiting for reply

  • Guarded suspension - requires both a lock and a precondition before execution

  • Join - means to write concurrent, parallel and distributed applications by message passing

  • Lock - resources can be accessed only by one thread at a time, locking the resource by the first thread to ask for it

  • Messaging - interchange of messages in network-oriented architectures

  • Monitor object - enables mutual exclusion and condition fulfilling in thread concurrency

  • Reactor - asynchronous interface to resources handled synchronously

  • Read/write lock - allows concurrent read operations but exclusive access to write operations

  • Scheduler - determine the points in time for threads to be executed

  • Thread pool - create several threads to perform tasks organized in a queue

  • Thread-local storage - use global variables as locals in threads to prevent concurrent overrides


When design patterns are used in the wrong way, making the application hard to maintain, rather inefficient and unproductive then they're actually anti-patterns. The main purpose of design patterns is to make a developer's life easier and therefore anti-patterns should be avoided. You can find other interesting articles on similar topics here.


34 views0 comments

Recent Posts

See All


A NEW AND FAST PACKAGE MANAGER There is a new kid on the block, and long story short, he is quite AWESOME. We are talking about YARN, a new package manager that wants to solve a few problems that have

Quick SSH access

HOW TO NOT GET LOST IN THE FOREST OF SSH SERVERS YOU HAVE TO WORK WITH For 8vance, one of the more complex projects that we're working on here in Cluj, we have a growing infrastructure - about 15 serv


bottom of page