The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (2024)

/ #Design Patterns
The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (1)
Sameeha Rahman
The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (2)

Design patterns are design level solutions for recurring problems that we software engineers come across often. It’s not code - I repeat, CODE. It is like a description on how to tackle these problems and design a solution.

Using these patterns is considered good practice, as the design of the solution is quite tried and tested, resulting in higher readability of the final code. Design patterns are quite often created for and used by OOP Languages, like Java, in which most of the examples from here on will be written.

Types of design patterns

There are about 26 Patterns currently discovered (I hardly think I will do them all…).

These 26 can be classified into 3 types:

1. Creational: These patterns are designed for class instantiation. They can be either class-creation patterns or object-creational patterns.

2. Structural: These patterns are designed with regard to a class's structure and composition. The main goal of most of these patterns is to increase the functionality of the class(es) involved, without changing much of its composition.

3. Behavioral: These patterns are designed depending on how one class communicates with others.

In this post, we will go through one basic design pattern for each classified type.

Type 1: Creational - The Singleton Design Pattern

The Singleton Design Pattern is a Creational pattern, whose objective is to create only one instance of a class and to provide only one global access point to that object. One commonly used example of such a class in Java is Calendar, where you cannot make an instance of that class. It also uses its own getInstance()method to get the object to be used.

A class using the singleton design pattern will include,

The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (3)
  1. A private static variable, holding the only instance of the class.
  2. A private constructor, so it cannot be instantiated anywhere else.
  3. A public static method, to return the single instance of the class.

There are many different implementations of singleton design. Today, I’ll be going through the implementations of;

1. Eager Instantiation

2. Lazy Instantiation

3. Thread-safe Instantiation

Eager Beaver

public class EagerSingleton {// create an instance of the class.private static EagerSingleton instance = new EagerSingleton();// private constructor, so it cannot be instantiated outside this class.private EagerSingleton() { }// get the only instance of the object created.public static EagerSingleton getInstance() {return instance;}}

This type of instantiation happens during class loading, as the instantiation of the variable instance happens outside any method. This poses a hefty drawback if this class is not being used at all by the client application. The contingency plan, if this class is not being used, is the Lazy Instantiation.

Lazy Days

There isn’t much difference from the above implementation. The main differences are that the static variable is initially declared null, and is only instantiated within the getInstance() method if - and only if - the instance variable remains null at the time of the check.

public class LazySingleton {// initialize the instance as null.private static LazySingleton instance = null;// private constructor, so it cannot be instantiated outside this class.private LazySingleton() { }// check if the instance is null, and if so, create the object.public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}}

This fixes one problem, but another one still exists. What if two different clients access the Singleton class at the same time, right to the millisecond? Well, they will check if the instance is null at the same time, and will find it true, and so will create two instances of the class for each request by the two clients. To fix this, Thread Safe instantiation is to be implemented.

(Thread) Safety is Key

In Java, the keyword synchronized is used on methods or objects to implement thread safety, so that only one thread will access a particular resource at one time. The class instantiation is put within a synchronized block so that the method can only be accessed by one client at a given time.

public class ThreadSafeSingleton {// initialize the instance as null.private static ThreadSafeSingleton instance = null;// private constructor, so it cannot be instantiated outside this class.private ThreadSafeSingleton() { }// check if the instance is null, within a synchronized block. If so, create the objectpublic static ThreadSafeSingleton getInstance() {synchronized (ThreadSafeSingleton.class) {if (instance == null) {instance = new ThreadSafeSingleton();}}return instance;}}

The overhead for the synchronized method is high, and reduces the performance of the whole operation.

For example, if the instance variable has already been instantiated, then each time any client accesses the getInstance() method, the synchronized method is run and the performance drops. This just happens in order to check if the instance variables’ value is null. If it finds that it is, it leaves the method.

To reduce this overhead, double locking is used. The check is used before the synchronized method as well, and if the value is null alone, does the synchronized method run.

// double locking is used to reduce the overhead of the synchronized methodpublic static ThreadSafeSingleton getInstanceDoubleLocking() {if (instance == null) {synchronized (ThreadSafeSingleton.class) {if (instance == null) {instance = new ThreadSafeSingleton();}}}return instance;}

Now onto the next classification.

Type 2: Structural - The Decorator Design Pattern

I’m gonna give you a small scenario to give a better context to why and where you should use the Decorator Pattern.

Say you own a coffee shop, and like any newbie, you start out with just two types of plain coffee, the house blend and dark roast. In your billing system, there was one class for the different coffee blends, which inherits the beverage abstract class. People actually start to come by and have your wonderful (albeit bitter?) coffee. Then there are the coffee newbs that, God forbid, want sugar or milk. Such a travesty for coffee!! ??

Now you need to have those two add-ons as well, both to the menu and unfortunately on the billing system. Originally, your IT person will make a subclass for both coffees, one including sugar, the other milk. Then, since customers are always right, one says these dreaded words:

“Can I get a milk coffee, with sugar, please?”

???

There goes your billing system laughing in your face again. Well, back to the drawing board….

The IT person then adds milk coffee with sugar as another subclass to each parent coffee class. The rest of the month is smooth sailing, people lining up to have your coffee, you actually making money. ??

But wait, there’s more!

The world is against you once again. A competitor opens up across the street, with not just 4 types of coffee, but more than 10 add-ons as well!

You buy all those and more, to sell better coffee yourself, and just then remember that you forgot to update that dratted billing system. You quite possibly cannot make the infinite number of subclasses for any and all combinations of all the add-ons, with the new coffee blends too. Not to mention, the size of the final system.

Time to actually invest in a proper billing system. You find new IT personnel, who actually knows what they are doing and they say,

“Why, this will be so much easier and smaller if it used the decorator pattern.”

What on earth is that?

The decorator design pattern falls into the structural category, that deals with the actual structure of a class, whether is by inheritance, composition or both. The goal of this design is to modify an objects’ functionality at runtime. This is one of the many other design patterns that utilize abstract classes and interfaces with composition to get its desired result.

Let’s give Math a chance (shudder?) to bring this all into perspective.

Take 4 coffee blends and 10 add-ons. If we stuck to the generation of subclasses for each different combination of all the add-ons for one type of coffee. That’s:

(10–1)² = 9² = 81 subclasses

We subtract 1 from the 10, as you cannot combine one add-on with another of the same type, sugar with sugar sounds stupid. And that’s for just one coffee blend. Multiply that 81 by 4 and you get a whopping 324 different subclasses! Talk about all that coding…

But with the decorator pattern it will require only 16 classes in this scenario. Wanna bet?

The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (4)
The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (5)

If we map out our scenario according to the class diagram above, we get 4 classes for the 4 coffee blends, 10 for each add-on and 1 for the abstract component and 1 more for the abstract decorator. See! 16! Now hand over that $100.?? (jk, but it will not be refused if given… just saying)

As you can see from above, just as the concrete coffee blends are subclasses of the beverage abstract class, the AddOn abstract class also inherits its methods from it. The add-ons, that are its subclasses, in turn inherit any new methods to add functionality to the base object when needed.

Let’s get to coding, to see this pattern in use.

First to make the Abstract beverage class, that all the different coffee blends will inherit from:

public abstract class Beverage {private String description; public Beverage(String description) {super();this.description = description;} public String getDescription() {return description;} public abstract double cost();}

Then to add both the concrete coffee blend classes.

public class HouseBlend extends Beverage {public HouseBlend() {super(“House blend”);}@Overridepublic double cost() {return 250;}}public class DarkRoast extends Beverage {public DarkRoast() {super(“Dark roast”);}@Overridepublic double cost() {return 300;}}

The AddOn abstract class also inherits from the Beverage abstract class (more on this below).

public abstract class AddOn extends Beverage {protected Beverage beverage;public AddOn(String description, Beverage bev) {super(description);this.beverage = bev;}public abstract String getDescription();}

And now the concrete implementations of this abstract class:

public class Sugar extends AddOn {public Sugar(Beverage bev) {super(“Sugar”, bev);}@Overridepublic String getDescription() {return beverage.getDescription() + “ with Mocha”;}@Overridepublic double cost() {return beverage.cost() + 50;}}public class Milk extends AddOn {public Milk(Beverage bev) {super(“Milk”, bev);}@Overridepublic String getDescription() {return beverage.getDescription() + “ with Milk”;}@Override public double cost() {return beverage.cost() + 100;}}

As you can see above, we can pass any subclass of Beverage to any subclass of AddOn, and get the added cost as well as the updated description. And, since the AddOn class is essentially of type Beverage, we can pass an AddOn into another AddOn. This way, we can add any number of add-ons to a specific coffee blend.

Now to write some code to test this out.

public class CoffeeShop {public static void main(String[] args) {HouseBlend houseblend = new HouseBlend();System.out.println(houseblend.getDescription() + “: “ + houseblend.cost());Milk milkAddOn = new Milk(houseblend);System.out.println(milkAddOn.getDescription() + “: “ + milkAddOn.cost());Sugar sugarAddOn = new Sugar(milkAddOn);System.out.println(sugarAddOn.getDescription() + “: “ + sugarAddOn.cost());}}

The final result is:

The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (6)

It works! We were able to add more than one add-on to a coffee blend and successfully update its final cost and description, without the need to make infinite subclasses for each add-on combination for all coffee blends.

Finally, to the last category.

Type 3: Behavioral - The Command Design Pattern

A behavioral design pattern focuses on how classes and objects communicate with each other. The main focus of the command pattern is to inculcate a higher degree of loose coupling between involved parties (read: classes).

Uhhhh… What’s that?

Coupling is the way that two (or more) classes that interact with each other, well, interact. The ideal scenario when these classes interact is that they do not depend heavily on each other. That’s loose coupling. So, a better definition for loose coupling would be, classes that are interconnected, making the least use of each other.

The need for this pattern arose when requests needed to be sent without consciously knowing what you are asking for or who the receiver is.

In this pattern, the invoking class is decoupled from the class that actually performs an action. The invoker class only has the callable method execute, which runs the necessary command, when the client requests it.

Let’s take a basic real-world example, ordering a meal at a fancy restaurant. As the flow goes, you give your order (command) to the waiter (invoker), who then hands it over to the chef(receiver), so you can get food. Might sound simple… but a bit meh to code.

The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (7)

The idea is pretty simple, but the coding goes around the nose.

The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (8)

The flow of operation on the technical side is, you make a concrete command, which implements the Command interface, asking the receiver to complete an action, and send the command to the invoker. The invoker is the person that knows when to give this command. The chef is the only one who knows what to do when given the specific command/order. So, when the execute method of the invoker is run, it, in turn, causes the command objects’ execute method to run on the receiver, thus completing necessary actions.

What we need to implement is;

  1. An interface Command
  2. A class Order that implements Command interface
  3. A class Waiter (invoker)
  4. A class Chef (receiver)

So, the coding goes like this:

Chef, the receiver

public class Chef {public void cookPasta() {System.out.println(“Chef is cooking Chicken Alfredo…”);}public void bakeCake() {System.out.println(“Chef is baking Chocolate Fudge Cake…”);}}

Command, the interface

public interface Command {public abstract void execute();}

Order, the concrete command

public class Order implements Command {private Chef chef;private String food;public Order(Chef chef, String food) {this.chef = chef;this.food = food;}@Overridepublic void execute() {if (this.food.equals(“Pasta”)) {this.chef.cookPasta();} else {this.chef.bakeCake();}}}

Waiter, the invoker

public class Waiter {private Order order;public Waiter(Order ord) {this.order = ord;}public void execute() {this.order.execute();}}

You, the client

public class Client {public static void main(String[] args) {Chef chef = new Chef(); Order order = new Order(chef, “Pasta”);Waiter waiter = new Waiter(order);waiter.execute();order = new Order(chef, “Cake”);waiter = new Waiter(order);waiter.execute();}}

As you can see above, the Client makes an Order and sets the Receiver as the Chef. The Order is sent to the Waiter, who will know when to execute the Order (i.e. when to give the chef the order to cook). When the invoker is executed, the Orders’ execute method is run on the receiver (i.e. the chef is given the command to either cook pasta ? or bake cake?).

The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (9)

Quick recap

In this post we went through:

  1. What a design pattern really is,
  2. The different types of design patterns and why they are different
  3. One basic or common design pattern for each type

I hope this was helpful.

Find the code repo for the post, here.

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

ADVERTIsem*nT

The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (10)
Sameeha Rahman

Read more posts.

If you read this far, thank the author to show them you care.

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

ADVERTIsem*nT

The 3 Types of Design Patterns All Developers Should Know (with code examples of each) (2024)

FAQs

The 3 Types of Design Patterns All Developers Should Know (with code examples of each)? ›

Design Patterns are categorized mainly into three categories: Creational Design Pattern, Structural Design Pattern, and Behavioral Design Pattern. These are differed from each other on the basis of their level of detail, complexity, and scale of applicability to the entire system being design.

What are the three types of design patterns? ›

Design Patterns are categorized mainly into three categories: Creational Design Pattern, Structural Design Pattern, and Behavioral Design Pattern. These are differed from each other on the basis of their level of detail, complexity, and scale of applicability to the entire system being design.

What are the three design patterns every developer should learn? ›

Design Pattern Catalog

Creational patterns deal with the process of object creation. Structural patterns are concerned with the composition of classes or objects. Behavioral patterns do characterization of how classes or objects interact and distribute responsibly.

What are design patterns with example? ›

Design patterns provide a standard terminology and are specific to particular scenario. For example, a singleton design pattern signifies use of single object so all developers familiar with single design pattern will make use of single object and they can tell each other that program is following a singleton pattern.

What is the design pattern rule of three? ›

Like in graphic design, the rule of thirds in UI (User Interface) design is a fundamental principle that helps structure and organize elements on a screen. It involves dividing the screen into a 3x3 grid, which results in nine equal parts. Usually, the four intersections are ideal for placing crucial elements.

What are the three main types of design? ›

I tend to divide design into three main types: product, interface, and visual.
  • Product Design. ...
  • Interface Design. ...
  • Visual Design. ...
  • Interrelation of types.
Dec 5, 2012

What are the 3 main design principles of object-oriented programming? ›

There are three major pillars on which object-oriented programming relies: encapsulation, inheritance, and polymorphism.

What are coding patterns? ›

Pattern coding is a useful second cycle approach to facilitate this process of refinement. More specifically, pattern coding aims to reduce the number of codes from your initial round of coding and decide how to best categorize your pre-existing codes.

What are the three types of programming design? ›

Surprisingly, it can often be distilled down to only three fundamental programming constructs: loops, selections, and sequences. Combining these results in the most basic instructions and algorithms for all types of software.

What are good examples of patterns? ›

What Are Some Examples Of Patterns In Real Life?
  • Musical Patterns.
  • Clapping Games.
  • Shapes.
  • Body Parts.
  • Seasons.
  • Day and Night.
  • Fibonacci Sequence.
  • Colors.
Dec 30, 2022

What are the design patterns for common code? ›

What are the common types of design patterns? Design patterns are categorized into three main types: creational, structural, and behavioral. Creational patterns deal with object creation, structural patterns with object composition, and behavioral patterns with object collaboration and responsibility.

Are there different types of patterns? ›

There are different types of patterns, such as number patterns, image patterns, logic patterns, word patterns etc. Number patterns are very common in Mathematics. These are quite familiar to the students who study Maths frequently. Especially, number patterns are everywhere in Mathematics.

What is the rule of 3 in design? ›

What is the "Rule of Three" In a nutshell, the rule of three suggests that things grouped in threes are more natural, harmonious and visually appealing. Odd numbers challenge our brains a bit and are more interesting.

What is the rule of 3 code? ›

It states that two instances of similar code do not require refactoring, but when similar code is used three times, it should be extracted into a new procedure. The rule was popularised by Martin Fowler in Refactoring and attributed to Don Roberts.

What is the design theory of 3? ›

The rule of thirds is a method of breaking up an image or design into different sections using columns and rows that form a grid. The grid consists of three evenly-spaced rows and columns to make nine equal boxes that fit over the image. The grid on your phone's camera is a great example of this.

How many patterns are there in design patterns? ›

The book is divided into two parts, with the first two chapters exploring the capabilities and pitfalls of object-oriented programming, and the remaining chapters describing 23 classic software design patterns.

What are oop design patterns? ›

Design patterns are reusable solutions to common problems in object-oriented programming (OOP). They help you write cleaner, more maintainable, and more flexible code. In this article, you will learn about some of the most common design patterns you use in OOP and how they can benefit your projects.

What are the four basic categories for design patterns? ›

Design patterns can be classified into different types and categories, often grouped into classes and subclasses based on their characteristics and applications. The various types of design patterns include idioms, architectural patterns, creation, structural, and behavioral patterns.

Top Articles
Latest Posts
Article information

Author: Maia Crooks Jr

Last Updated:

Views: 6301

Rating: 4.2 / 5 (63 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Maia Crooks Jr

Birthday: 1997-09-21

Address: 93119 Joseph Street, Peggyfurt, NC 11582

Phone: +2983088926881

Job: Principal Design Liaison

Hobby: Web surfing, Skiing, role-playing games, Sketching, Polo, Sewing, Genealogy

Introduction: My name is Maia Crooks Jr, I am a homely, joyous, shiny, successful, hilarious, thoughtful, joyous person who loves writing and wants to share my knowledge and understanding with you.