DEV Community

Cover image for Design Patterns: Make your code modular
Lovepreet Singh
Lovepreet Singh

Posted on • Updated on

Design Patterns: Make your code modular

Whenever we start learning to code, Either we start from solving Data structures and Algorithms problems or We start from web development. It varies person to person, But one thing that most of us ignore is:- Design Patterns

Design Patterns

Yes, It is right you will end up changing code too frequent if you haven't thought about the design at the start.

Always Remember, Software Development is 50% Solutionising, 30% Debugging and 20% Coding. While Solutionising first priority will always be modular, well designed and loosely coupled code.

➪ Today we'll dive deeper into the design patterns that can be followed while coding.

📌 Strategy Design Pattern


This pattern suggests that when a class does a thing in so many different ways then you can take those all different things/algorithms and make them different strategies.

Example:- Let say you own a Map app where you suggest path from A to B via Vehicle only. But now in v2 release you want to add walk and public transport also. So, in our Navigator we can use different strategies to navigate i.e.

  • Walk
  • Vehicle
  • Public Transport

These different strategies can be combined in an interface as:-

Strategy pattern
Image Reference:- Refactoring Guru

Navigator "has-a" relationship with Route Strategy which means It contains a RouteStrategy Interface. Road Strategy, PublicTransport Strategy and Walking Strategy "is-a" relationship with RouteStrategy.

Dont't worry we'll dive deeper in the code:-

public interface RouteStrategy{
    public void buildRoot(int x1, int x2, int y1, int y2);
}

public class RoadStrategy implements RouteStrategy{
    @Override
    public void buildRoot(int x1, int x2, int y1, int y2){
        // Build root via Road
    }
}

public class PublicTransportStrategy implements RouteStrategy{
    @Override
    public void buildRoot(int x1, int x2, int y1, int y2){
        // Build root via Public Transport
    }
}

public class WalkingStrategy implements RouteStrategy{ // is-a relationship with RouteStrategy
    @Override
    public void buildRoot(int x1, int x2, int y1, int y2){
        // Build root via Public Walk
    }
}

public class Navigator{
    private RouteStrategy routeStrategy; // has-a relationship with RouteStrategy

    public Navigator(RouteStrategy routeStrategy){
        this.routeStrategy = routeStrategy;
    }

    public void buildRoot(int x1, int x2, int y1, int y2){
        routeStrategy.buildRoot(x1, x2, y1, y2);
    }

}
Enter fullscreen mode Exit fullscreen mode

📌 Observer Design Pattern


This pattern is kind of subscription based or observing someone.

Observer Design Pattern
Image Reference:- Refactoring Guru

Let say when you go on amazon and wanted to buy a "T-shirt" but that particular one is out of stock. Then, what you do is you click on Notify me when available. So, there you are doing nothing but creating an observer that will keep observing once the stock will be available.

Out of stock

Flipkart out of stock, Notify me button

Observer Design Pattern
Image Reference:- Refactoring Guru

Now, whenever something will happen inside the Publisher it will notify its subscribers that can further take different actions like sending a notification to a user.

These Publishers and Subscribers are also known as Observables and Observers respectively.

import java.util.ArrayList;

public interface ProductNotifyObserver{ 
// Subscribers Interface
    public void update(Object o);
}

public class SmartPhonesNotify implements ProductNotifyObserver{ 
// Smartphone specific observer
    private String userId;
    private String productId;

    @Override
    public void update(Object o){
        this.userId = o.getUserId;
        this.productId = o.getProductId;
        // Call notify service to send a notification to the user
    }
}

public class ProductNotifyObservable{ 
// Publisher or Observable
    List<ProductNotifyObserver> observables = new ArrayList();

    public void addProduct(ProductNotifyObserver p){ 
// user is clicking on Notify-me button and we add that Product into our list
        this.observables.add(p);
    }
    public void removeProduct(ProductNotifyObserver p){
        this.observables.remove(p);
    }
    public void setProduct(Product product){ // product gets back in stock
        for(ProductNotifyObservable p : this.observables){
            if(p.getProductId == product.getProductId){
                p.update(product);
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

So, referring to the above pseudo code, It is clear that whenever a product comes back in stock. We can call the observable setProduct(Product p) that will call all the observers that are specific to that product only (Observers are the users clicked on notify me) will trigger the update() method of that specific observer only.

📌 This is it for today, In part 2 we will cover design patterns like Decorator and Factory. Follow for more such in depth content.

Follow on 🐥 Twitter for more updates and daily learnings

Top comments (2)

Collapse
 
westial profile image
Jaume

Let me disagree with your assumption as "Always Remember, Software Development is 50% Solutionising, 30% Debugging and 20% Coding". I guess you are talking about what James Grenning calls Debug Later Programming, or DLP. There are other approaches. blog.wingman-sw.com/physics-of-tes...

Collapse
 
lovepreetsingh profile image
Lovepreet Singh

It is my personal experience. I didn't quote from any book. 🙂