<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Suman Pal</title>
    <description>The latest articles on DEV Community by Suman Pal (@sumanpal97).</description>
    <link>https://dev.to/sumanpal97</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1171720%2F8efad6c0-6a30-46b5-9bb1-8572ff9e130a.jpg</url>
      <title>DEV Community: Suman Pal</title>
      <link>https://dev.to/sumanpal97</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sumanpal97"/>
    <language>en</language>
    <item>
      <title>Structural Design Patterns Decoded: Your Key to Agile and Robust Software</title>
      <dc:creator>Suman Pal</dc:creator>
      <pubDate>Mon, 02 Oct 2023 18:18:09 +0000</pubDate>
      <link>https://dev.to/sumanpal97/structural-design-patterns-decoded-your-key-to-agile-and-robust-software-1j74</link>
      <guid>https://dev.to/sumanpal97/structural-design-patterns-decoded-your-key-to-agile-and-robust-software-1j74</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftg1is6kxd1gv5m14gzfy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftg1is6kxd1gv5m14gzfy.jpg" alt="Structural  Design Patterns"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Structural Design Pattern serves as a blueprint of how various objects and classes can be orchestrated to construct a larger and more complex framework, all with the aim of fulfilling multiple objectives simultaneously.&lt;/p&gt;




&lt;p&gt;This article aims to present a detailed explanation of seven structural design patterns with respective UML and Sequence Diagrams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adapter Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Intent&lt;/strong&gt; -  The Adapter Pattern allows objects with incompatible interfaces to work together. It acts as a bridge between two incompatible interfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use when you need to make existing classes work with others that have incompatible interfaces.&lt;/li&gt;
&lt;li&gt;When integrating new components into an existing system without modifying existing code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides a wrapper to adapt one interface to another.&lt;/li&gt;
&lt;li&gt;Useful for maintaining code flexibility and reusability.&lt;/li&gt;
&lt;li&gt;Helps bridge the gap between different components or systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgn5it1epggc1h97s980.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgn5it1epggc1h97s980.jpg" alt="adapter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; - &lt;br&gt;
Imagine trying to charge an iPhone using an Android Charger, but we can't directly do that. so we are using an "ADAPTER" to convert Android to iPhone subsystem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface AndroidCharger {
    void chargerAndroidPhone();
}
interface AppleCharger {
    void chargeIPhone();
}
class SamsungCharger implements AndroidCharger {
    @Override
    public void chargerAndroidPhone() {
        System.out.println("Your phone is charging using SamsungCharger");
    }
}
class IPhoneCharger implements AppleCharger {
    @Override
    public void chargeIPhone() {
        System.out.println("your phone is charging using IPhoneCharger");
    }
}

class Iphone13 {
    private AppleCharger appleCharger;
    public Iphone13(AppleCharger appleCharger) {
        this.appleCharger = appleCharger;
    }
    public void chargeIphone() {
        appleCharger.chargeIPhone();
    }
}

class AndroidToAppleAdapterCharger implements AppleCharger {
    private AndroidCharger charger;
    public AndroidToAppleAdapterCharger(AndroidCharger charger) {
        this.charger = charger;
    }
    @Override
    public void chargeIPhone() {
        charger.chargerAndroidPhone();
        System.out.println("your phone is charging with adapter");
    }
}

public class Client {
    public static void main(String[] args) {
        /*charging iPhone with iPhone Charger scenario
        AppleCharger iphoneCharger = new IPhoneCharger();
        Iphone13 iphone13 = new Iphone13(iphoneCharger);
        iphone13.chargeIphone();*/

        AndroidCharger androidCharger = new SamsungCharger();
        AppleCharger androidToAppleAdapterCharger = new AndroidToAppleAdapterCharger(androidCharger);

        Iphone13 iphone13 = new Iphone13(androidToAppleAdapterCharger);
        iphone13.chargeIphone();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Proxy Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Intent&lt;/strong&gt; - &lt;br&gt;
Proxy means ‘in place of’ or ‘on behalf of’ that directly explains Proxy Design Pattern.&lt;br&gt;
The Proxy Pattern controls access to an object by acting as an intermediary. It can be used to add additional behavior or control access to a real object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt; - &lt;br&gt;
Use when you need to control access to an object, add additional behavior, or defer object creation.&lt;br&gt;
When you want to manage resource-intensive operations efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt; - &lt;br&gt;
Can be applied to implement lazy loading, access control, logging, or monitoring.&lt;br&gt;
Useful for optimizing performance and managing resources effectively.&lt;br&gt;
Different types of proxies (e.g., virtual, remote) cater to various use cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fungh8vaff7wn44ar4id8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fungh8vaff7wn44ar4id8.jpg" alt="proxy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; - &lt;br&gt;
A simple real-life scenario is that the college internet system employs a protection proxy that effectively restricts access to certain websites. It verifies the host being connected to and only allows access to the real internet if it is not on the restricted site list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

interface Internet{
    public void connectTo(String serverhost) throws Exception;
}

class RealInternet implements Internet{
    public void connectTo(String serverhost){
        System.out.println("Connecting to "+ serverhost);
    }
}

class ProxyInternet implements Internet{
    private Internet internet = new RealInternet();
    private static List&amp;lt;String&amp;gt; bannedSites;

    ProxyInternet(){
        bannedSites = new ArrayList&amp;lt;String&amp;gt;();
        bannedSites.add("whatsapp.com");
        bannedSites.add("facebook.com");
        bannedSites.add("instagram.com");
    }

    public void connectTo(String serverhost) throws Exception{
        if(bannedSites.contains(serverhost.toLowerCase())){
            throw new Exception("Access Denied");
        }
        internet.connectTo(serverhost);
    }
}

public class Client{
    public static void main (String[] args) {
        Internet internet = new ProxyInternet();
        try{
            internet.connectTo("google.com");
            internet.connectTo("facebook.com");
        }
        catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Decorator Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Intent&lt;/strong&gt; - &lt;br&gt;
The Decorator Pattern dynamically adds new responsibilities to objects without altering their class. It is used to extend the functionalities of objects at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt; - &lt;br&gt;
Use when you want to add responsibilities to objects dynamically without altering their classes.&lt;br&gt;
When you need to extend an object's behavior in a flexible and reusable way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt; - &lt;br&gt;
Enables the open-closed principle, allowing you to add new functionality without modifying existing code.&lt;br&gt;
Multiple decorators can be combined to create various combinations of behavior.&lt;br&gt;
Useful for adding features such as logging, encryption, or formatting to existing classes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnukukaduzfgenpspczoa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnukukaduzfgenpspczoa.jpg" alt="decorator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; -&lt;br&gt;
A real-life scenario would be decorating or updating the features of a basic car into a Sports Car or Luxury Car, without modifying existing code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Car {
    public void makeCar();
}

class SimpleCar implements Car {
    public void makeCar() {
        System.out.print("Simple Car.");
    }
}

class CarDecorator implements Car {
    protected Car car;

    public CarDecorator(Car car){
        this.car=car;
    }
    public void makeCar() {
        this.car.makeCar();
    }
}

class SportsCar extends CarDecorator {
    public SportsCar(Car car) {
        super(car);
    }
    public void makeCar(){
        super.makeCar();
        addNitro();
    }
    public void addNitro(){
        System.out.print(" Tranforming into a Sports Car.");
    }
}

class LuxuryCar extends CarDecorator {
    public LuxuryCar(Car c) {
        super(c);
    }
    public void makeCar(){
        super.makeCar();
        addComfort();
    }
    public void addComfort(){
        System.out.print(" Tranforming into a Luxury Car.");
    }
}

public class Client{

    public static void main(String[] args) {
        Car sportsCar = new SportsCar(new SimpleCar());
        sportsCar.makeCar();
        System.out.println("\n*****");

        Car sportsLuxuryCar = new SportsCar(new LuxuryCar(new SimpleCar()));
        sportsLuxuryCar.makeCar();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;&lt;em&gt;Interesting points:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The Adapter pattern presents a distinct interface for its subject, whereas the Proxy pattern maintains the original object's interface. In contrast, the Decorator pattern enhances the interface and adds supplementary functionality dynamically during runtime.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Composite Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Intent&lt;/strong&gt; - &lt;br&gt;
The Composite Pattern composes objects into tree structures to represent part-whole hierarchies. Clients can treat individual objects and compositions of objects uniformly.&lt;/p&gt;

&lt;p&gt;The Composite Pattern has three participants:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Component&lt;/strong&gt;– The component defines the interface for composition objects and facilitates access and management of its child components. It also incorporates default behavior for the interface that is applicable to all classes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leaf&lt;/strong&gt;– The leaf component establishes the behavior for basic objects within the composition, specifically representing the individual leaf objects present in the composition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composite&lt;/strong&gt;– The composite stores child components and implements operations related to the child components within the component interface.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt; - &lt;br&gt;
Use when you need to represent part-whole hierarchies, and clients should treat individual objects and compositions uniformly.&lt;br&gt;
When working with complex tree structures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt; - &lt;br&gt;
Simplifies client code by treating leaf objects and composites the same way.&lt;br&gt;
Supports recursive composition, enabling the creation of hierarchical structures.&lt;br&gt;
Useful for creating complex structures like graphics, GUIs, or organizational hierarchies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6clh94k02n2a9hxczrzr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6clh94k02n2a9hxczrzr.jpg" alt="hierarchy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xulkcruxl15ewtcw8kh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xulkcruxl15ewtcw8kh.jpg" alt="Composite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; - &lt;br&gt;
Let's take an example of the hierarchy of an organization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

interface Employee//Component 
{
    public void showEmployeeDetails();
}

class Tester implements Employee//Leaf  
{
    private String name;
    private long empId;
    private String position;

    public Tester(long empId, String name, String position)
    {
        this.empId = empId;
        this.name = name;
                this.position = position;
    }

    @Override
    public void showEmployeeDetails()
    {
        System.out.println(empId+" " +name);
    }
}

class Developer implements Employee//Leaf  
{
    private String name;
    private long empId;
    private String position;

    public Developer(long empId, String name, String position)
    {
        this.empId = empId;
        this.name = name;
                this.position = position;
    }

    @Override
    public void showEmployeeDetails()
    {
        System.out.println(empId+" " +name);
    }
}

class Manager implements Employee//Leaf  
{
    private String name;
    private long empId;
        private String position;

    public Manager(long empId, String name, String position)
    {
        this.empId = empId;
        this.name = name;
                this.position = position;
    }

    @Override
    public void showEmployeeDetails()
    {
        System.out.println(empId+" " +name);
    }
}

class CompanyDirectory implements Employee//Composite  
{
    private List&amp;lt;Employee&amp;gt; employeeList = new ArrayList&amp;lt;Employee&amp;gt;();

    @Override
    public void showEmployeeDetails()
    {
        for(Employee emp:employeeList)
        {
            emp.showEmployeeDetails();
        }
    }

    public void addEmployee(Employee emp)
    {
        employeeList.add(emp);
    }

    public void removeEmployee(Employee emp)
    {
        employeeList.remove(emp);
    }
}

public class Client   
{
    public static void main (String[] args)
    {
        Tester tester = new Tester(100, "David", "Tester");
        Developer developer = new Developer(101, "Steve", "Developer");
        CompanyDirectory engDirectory = new CompanyDirectory();
        engDirectory.addEmployee(tester);
        engDirectory.addEmployee(developer);

        Manager man1 = new Manager(200, "Tom", "Manager");
        Manager man2 = new Manager(201, "Robert", "Manager");

        CompanyDirectory managerDirectory = new CompanyDirectory();
        managerDirectory.addEmployee(man1);
        managerDirectory.addEmployee(man2);

        CompanyDirectory companyDirectory = new CompanyDirectory();
        companyDirectory.addEmployee(engDirectory);
        companyDirectory.addEmployee(managerDirectory);

        companyDirectory.showEmployeeDetails();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Fly Weight Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Intent&lt;/strong&gt; - &lt;br&gt;
The Flyweight Pattern minimizes memory usage or computational expenses by sharing as much as possible with related objects. It is often used for managing a large number of similar objects efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt; - &lt;br&gt;
Use when you have a large number of similar objects, and memory usage or computational expenses need to be minimized.&lt;br&gt;
When managing objects with shared intrinsic properties and varying extrinsic properties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt; - &lt;br&gt;
Shares common, immutable parts of objects to reduce memory overhead.&lt;br&gt;
Useful for optimizing resource usage, especially in scenarios like graphical systems.&lt;br&gt;
Separates intrinsic (shared) and extrinsic (unique) states for efficient memory management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6bauwnjavakd7u4qw79.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6bauwnjavakd7u4qw79.jpg" alt="flyweight"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; - &lt;br&gt;
Let's say we want to create a game map. And there is a forest present in a part of the game map. So we need to create lots of trees. so instead of creating an object for each tree, we will use a single object for Tree. Let's see how can we achieve that using the FlyWeight Pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.HashMap;
import java.util.Random;

interface Tree {
    public void swingLeaves();
}

class OakTree implements Tree {
    private final String height;

    public OakTree(){
        height = "1.4m";
    }
    public void swingLeaves(){
        System.out.println("Leaves of Oak Tree are swinging");
    }
}

class PineTree implements Tree {
    private final String height;

    public PineTree(){
        height = "2.4m";
    }
    public void swingLeaves(){
        System.out.println("Leaves of Pine Tree are swinging");
    }
}

class BanyanTree implements Tree {
    private final String height;

    public BanyanTree(){
        height = "1.1m";
    }
    public void swingLeaves(){
        System.out.println("Leaves of Banyan Tree are swinging");
    }
}


class ForestFactory
{
    private static HashMap &amp;lt;String, Tree&amp;gt; forestMap = new HashMap&amp;lt;String, Tree&amp;gt;();

    public static Tree getTree(String type)
    {
        Tree tree = null;

        if (forestMap.containsKey(type))
                tree = forestMap.get(type);
        else
        {
            switch(type){
            case "OakTree":
                System.out.println("Oak Tree Created");
                tree = new OakTree();
                break;
            case "PineTree":
                System.out.println("Pine Tree Created");
                tree = new PineTree();
                break;
            case "BanyanTree":
                System.out.println("Banyan Tree Created");
                tree = new BanyanTree();
                break;
            default :
                System.out.println("Wrong Type!");
            }
            forestMap.put(type, tree);
        }
        return tree;
    }
}

public class Client{
    private static String[] treeType = {"OakTree", "PineTree", "BanyanTree"};

    public static void main(String args[]){
        //creating forest with 10trees
        for (int i = 0; i &amp;lt; 10; i++){
            Tree tree = ForestFactory.getTree(getRandTreeType());
            tree.swingLeaves();
        }
    }

    public static String getRandTreeType(){
        int randInt = new Random().nextInt(treeType.length);
        return treeType[randInt];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Facade Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Intent&lt;/strong&gt; - &lt;br&gt;
The Facade Pattern provides a simplified interface to a complex subsystem. It acts as a high-level entry point for a set of interfaces in a system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt; - &lt;br&gt;
Use when you want to provide a simplified interface to a complex subsystem.&lt;br&gt;
When you need to encapsulate intricate subsystems to improve code maintainability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt; - &lt;br&gt;
Hides the complexity of a system from clients, providing a single, user-friendly entry point.&lt;br&gt;
Improves code readability and maintainability by abstracting subsystem details.&lt;br&gt;
Useful for simplifying interactions with external services, libraries, or complex modules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqja65ht1fnkjbgt99l6o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqja65ht1fnkjbgt99l6o.jpg" alt="Facade"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; - &lt;br&gt;
Consider a hotel with multiple restaurants, including vegetarian, non-vegetarian, and mixed cuisine options. As a guest, you may desire access to various menus but lack knowledge of the available options. Fortunately, the hotel keeper serves as a knowledgeable intermediary, retrieving your desired menu items from the appropriate restaurant. Here, the hotel keeper acts as the facade, as he hides the complexities of the system hotel. Let’s see how it works&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Menu{
    private String menu;
    Menu(String menu){
        this.menu=menu;
    }
    public String getMenuDetails(){
        return this.menu;
    }
}

interface Hotel {
    public Menu getMenu();
}

class NonVegRestaurant implements Hotel {
    public Menu getMenu(){
        return new Menu("Chicken");
    }
}

class VegRestaurant implements Hotel {
    public Menu getMenu(){
        return new Menu("Paneer");
    }
}

class VegAndNonVegRestaurant implements Hotel {
    public Menu getMenu(){
        return new Menu("Mutton and Mushroom");
    }
}

interface HotelKeeper {
    public Menu getVegMenu();
    public Menu getNonVegMenu();
    public Menu getVegAndNonVegMenu();
}

class HotelKeeperImplementation implements HotelKeeper {
    public Menu getVegMenu(){
        VegRestaurant vegRest = new VegRestaurant();
        return vegRest.getMenu();
    }
    public Menu getNonVegMenu(){
        NonVegRestaurant nonVegRest = new NonVegRestaurant();
        return nonVegRest.getMenu();
    }
    public Menu getVegAndNonVegMenu(){
        VegAndNonVegRestaurant vegNonVegRest = new VegAndNonVegRestaurant();
        return vegNonVegRest.getMenu();
    }
}

public class Client{
    public static void main (String[] args) {
        HotelKeeper keeper = new HotelKeeperImplementation();

        System.out.println("Menu of Veg Restaurant : " + keeper.getVegMenu().getMenuDetails());
        System.out.println("Menu of NonVeg Restaurant : " + keeper.getNonVegMenu().getMenuDetails());
        System.out.println("Menu of Veg &amp;amp; NonVeg Restaurant : " + keeper.getVegAndNonVegMenu().getMenuDetails());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Bridge Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Intent&lt;/strong&gt; - &lt;br&gt;
The Bridge Pattern separates an object's abstraction from its implementation, allowing them to vary independently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt; - &lt;br&gt;
Use when you want to separate the abstraction from its implementation, allowing them to vary independently.&lt;br&gt;
When dealing with multiple dimensions of variation in your system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt; - &lt;br&gt;
It enhances flexibility by decoupling the abstraction (interface) from the concrete implementation.&lt;br&gt;
Useful when you have multiple dimensions of variations, like different platforms or rendering methods.&lt;br&gt;
Promotes scalability as new abstractions or implementations can be added without affecting existing code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5pijj85vr59924mregq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5pijj85vr59924mregq.jpg" alt="bridge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; - &lt;br&gt;
We want to create a Device-remote system, where each device has a dedicated remote to access the device. So we want to segregate the Device and Remote from the implementation point of view. Let's see how can we achieve that using a Bridge Pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Right Side of the Bridge
interface Device{
    boolean deviceMode();
    void deviceOn();
    void deviceOff();
    void volumeUp();
    void volumeDown();
}

class TV implements Device{
    private boolean isTvOn = false;

    public boolean deviceMode(){
        return this.isTvOn;
    }
    public void deviceOn(){
        System.out.println("Tv is On");
        isTvOn = true;
    }
    public void deviceOff(){
        System.out.println("Tv is Off");
        isTvOn = false;
    }
    public void volumeUp(){
        System.out.println("Tv's volume is Up");
    }
    public void volumeDown(){
        System.out.println("Tv's volume is Down");
    }
}

class Radio implements Device{
    private boolean isRadioOn = false;

    public boolean deviceMode(){
        return this.isRadioOn;
    }
    public void deviceOn(){
        System.out.println("Radio is On");
        isRadioOn = true;
    }
    public void deviceOff(){
        System.out.println("Radio is Off");
        isRadioOn = false;
    }
    public void volumeUp(){
        System.out.println("Radio's volume is Up");
    }
    public void volumeDown(){
        System.out.println("Radio's volume is Down");
    }
}

//Left Side of the Bridge
abstract class Remote{
    public Device device;

    Remote(Device device){
        this.device = device;
    }

    public abstract void turnOnDevice();
    public abstract void turnOffDevice();
    public abstract void increaseDeviceVolume();
    public abstract void decreaseDeviceVolume();
}

class TvRemote extends Remote{
    TvRemote(Device device){
        super(device);
    }

    public void turnOnDevice(){
        device.deviceOn();
    }
    public void turnOffDevice(){
        device.deviceOff();
    }
    public void increaseDeviceVolume(){
        if(device.deviceMode())
            device.volumeUp();
        else
            System.out.println("Tv is Off. Can't increase volume. Please turn on TV first.");
    }
    public void decreaseDeviceVolume(){
        if(device.deviceMode())
            device.volumeDown();
        else
            System.out.println("Tv is Off. Can't decrease volume. Please turn on TV first.");
    }
}

class RadioRemote extends Remote{
    RadioRemote(Device device){
        super(device);
    }

    public void turnOnDevice(){
        device.deviceOn();
    }
    public void turnOffDevice(){
        device.deviceOff();
    }
    public void increaseDeviceVolume(){
        if(device.deviceMode())
            device.volumeUp();
        else
            System.out.println("Radio is Off. Can't increase volume. Please turn on Radio first.");
    }
    public void decreaseDeviceVolume(){
        if(device.deviceMode())
            device.volumeDown();
        else
            System.out.println("Radio is Off. Can't decrease volume. Please turn on Radio first.");
    }
}

public class Client
{
    public static void main(String[] args) {
        Device device = new TV();
        Remote remote = new TvRemote(device);

        remote.turnOnDevice();
        remote.increaseDeviceVolume();
        remote.decreaseDeviceVolume();
        remote.turnOffDevice();
        remote.increaseDeviceVolume();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;In conclusion, structural design patterns provide reusable blueprints for organizing and composing classes and objects, making our code more adaptable, maintainable, and scalable. By employing these patterns, developers can simplify complex system architectures, bridge incompatibilities between components, and create hierarchical structures efficiently. Understanding and applying structural design patterns is a fundamental skill for building robust, flexible, and elegant software solutions. Happy coding!&lt;br&gt;
I hope you found my blog enjoyable and informative.&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>oops</category>
      <category>lowleveldesign</category>
      <category>java</category>
    </item>
    <item>
      <title>Understanding Creational Design Patterns: A Comprehensive Guide</title>
      <dc:creator>Suman Pal</dc:creator>
      <pubDate>Thu, 28 Sep 2023 09:19:35 +0000</pubDate>
      <link>https://dev.to/sumanpal97/understanding-creational-design-patterns-a-comprehensive-guide-27jk</link>
      <guid>https://dev.to/sumanpal97/understanding-creational-design-patterns-a-comprehensive-guide-27jk</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs4eq9j0cy79ovu0nb3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs4eq9j0cy79ovu0nb3w.png" alt="Creational Design Pattern"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creational Design Patterns are a distinct category of design patterns that focus on the creation of objects and their associated mechanisms. These patterns offer techniques for object creation that conceal the underlying intricacies of instantiation and initialization. The primary objective of creational patterns is to enhance the flexibility, maintainability, and class independence of a system.&lt;/p&gt;




&lt;p&gt;This article aims to present a detailed explanation of six creational design patterns with respective UML and Sequence Diagrams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Singleton Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt; - Ensures that a class has only one instance and provides a global point of access to that instance. It's useful when exactly one object is needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why/When to use&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Single Instance Requirement&lt;/u&gt;: Use the Singleton pattern when you need to ensure that a class has only one instance throughout the application's lifetime.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Global Access&lt;/u&gt;: When multiple parts of your application need access to a single instance of an object, the Singleton provides a global point of access.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Resource Management&lt;/u&gt;: It's suitable for managing resources like database connections, logging, thread pools, or caches to avoid excessive resource allocation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Single Instance&lt;/u&gt;: Ensures that a class has only one instance throughout the application, which can be accessed globally.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Global Access&lt;/u&gt;: Provides a single point of access to the instance, making it easy to share data or coordinate actions across the system.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Resource Efficiency&lt;/u&gt;: Lazily initializes the instance, conserving resources until it's actually needed.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Thread Safety&lt;/u&gt;: Can be designed to be thread-safe, preventing issues with multiple threads accessing the instance simultaneously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58bppfg2qmhf753pl5mm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58bppfg2qmhf753pl5mm.jpg" alt="Singleton UML"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SingletonClass {
    private static SingletonClass singletonInstance;
    private SingletonClass(){
         System.out.println("Instance created");
    }
    public static SingletonClass getInstance(){
        if(singletonInstance == null){
            singletonInstance = new SingletonClass();
        }
        return singletonInstance;
    }
    public void simpleMethod(){
        System.out.println("hashcode of singelton object     " + singletonInstance);
    }
}

public class Client {
    public static void main(String[] args) {
        SingletonClass singletonClassObject = SingletonClass.getInstance();
        singletonClassObject.simpleMethod();

        SingletonClass singletonClassObject2 = SingletonClass.getInstance();
        singletonClassObject2.simpleMethod();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Prototype Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt; - Creates new objects by copying an existing object, known as a prototype. This pattern is useful when the cost of creating an object is more expensive or complex than copying an existing one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why/When to use&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Object Cloning&lt;/u&gt;: When you want to create new objects by copying an existing object, the Prototype pattern is valuable. This is especially useful when the cost of creating an object is high.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Customization of Objects&lt;/u&gt;: If you need to create similar objects with minor variations, the Prototype allows you to clone and customize objects as needed.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Performance Optimization&lt;/u&gt;: In situations where cloning is more efficient than creating objects from scratch, such as with large or complex objects, the Prototype pattern can improve performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Object Cloning&lt;/u&gt;: Creates new objects by copying an existing object, reducing the overhead of creating complex objects from scratch.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Customization&lt;/u&gt;: Allows customization of copied objects by modifying their attributes as needed.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Performance&lt;/u&gt;: Improves performance when object creation is more costly than cloning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fawgmv627g6aglpyyg5t8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fawgmv627g6aglpyyg5t8.jpg" alt="Prototype UML"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.List;
import java.util.ArrayList;

class Employees implements Cloneable {
    private List&amp;lt;String&amp;gt; employeeList;
    public Employees(){
        employeeList = new ArrayList&amp;lt;&amp;gt;();
    }
    public Employees(List&amp;lt;String&amp;gt; empList){
        this.employeeList = empList;
    }
    public List&amp;lt;String&amp;gt; getEmployeeList(){
        return employeeList;
    }
    public void setEmployeeList(List&amp;lt;String&amp;gt; empsList){
        this.employeeList = empsList;
    }
    public void loadEmployeeData(){
        employeeList.add("Tom");
        employeeList.add("David");
        employeeList.add("Steve");
    }

    @Override
    public Object clone() throws CloneNotSupportedException{
        List&amp;lt;String&amp;gt; temp = new ArrayList&amp;lt;&amp;gt;();
        for(String s : this.getEmployeeList()){
            temp.add(s);
        }

        return new Employees(temp);
    }
}

public class PrototypePattern{
    public static void main (String[] args) throws CloneNotSupportedException {
        Employees emps =  new Employees();
        emps.loadEmployeeData();

        //Use the clone method to get the Employee Object
        Employees empsNew = (Employees) emps.clone();
        Employees empsNew2 = (Employees) emps.clone();

        //modifying empsNew
        List&amp;lt;String&amp;gt; list = empsNew.getEmployeeList();
        list.add("Roger");
        empsNew.setEmployeeList(list);
        //modifying empsNew2
        List&amp;lt;String&amp;gt; list2 = empsNew2.getEmployeeList();
        list2.remove("David");
        empsNew2.setEmployeeList(list2);

        System.out.println("emps List : " + emps.getEmployeeList());
        System.out.println("empsNew List : " + empsNew.getEmployeeList());
        System.out.println("empsNew2 List : " + empsNew2.getEmployeeList());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Builder Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt; - It lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why/When to use&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Complex Object Construction&lt;/u&gt;: When object creation involves multiple steps, complex configurations, or optional parameters, the Builder pattern simplifies the construction process.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Fluent Interface&lt;/u&gt;: Use Builder when you want to provide a fluent and expressive way for clients to configure and build objects by chaining method calls.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Immutability&lt;/u&gt;: Builders often create immutable objects, making them suitable for scenarios where the object's state should not change after creation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Complex Object Construction&lt;/u&gt;: Separates the construction of a complex object from its representation, allowing for more control and flexibility in object creation.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Fluent Interface&lt;/u&gt;: Often implemented with a fluent interface, making code more readable and expressive when configuring objects.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Parameterization&lt;/u&gt;: Provides a way to construct objects with different configurations, reducing the need for multiple constructor overloads.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Choose what you need&lt;/u&gt;: When we have lots of attributes in a class, and we don't want every attribute every time. So we should be free to use any attribute based on our use requirement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts0aliltp1q1chm7wwhg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts0aliltp1q1chm7wwhg.jpg" alt="Builder UML"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface SkillsRating{
    public void setJava(int java);
    public void setDSA(int dsa);
    public void setSelenium(int selenium);
    public void setSpringBoot(int springBoot);
    public void setAWS(int aws);
    public void setReact(int react);
}

class SoftwareEngineer implements SkillsRating{
    private int java;
    private int dsa;
    private int selenium;
    private int springBoot;
    private int aws;
    private int react;

    public void setJava(int java){
        this.java=java;
    }
    public void setDSA(int dsa){
        this.dsa=dsa;
    }
    public void setSelenium(int selenium){
        this.selenium=selenium;
    }
    public void setSpringBoot(int springBoot){
        this.springBoot=springBoot;
    }
    public void setAWS(int aws){
        this.aws=aws;
    }
    public void setReact(int react){
        this.react=react;
    }
    public void showSkillsDetails(String role){
        System.out.println(role + " =&amp;gt;  Java : " + java + "| DSA : " + dsa + "| Selenium : " + selenium +
                            "| SpringBoot : " + springBoot + "| AWS : " + aws + "| React : " + react);
    }
}

interface SkillsBuilder{
    public SkillsBuilder setJavaSkill(int java);
    public SkillsBuilder setDSASkill(int dsa);
    public SkillsBuilder setSeleniumSkill(int selenium);
    public SkillsBuilder setSpringBootSkill(int springBoot);
    public SkillsBuilder setAWSSkill(int aws);
    public SkillsBuilder setReactSkill(int react);
    public SoftwareEngineer getSoftwareEngineer();
}

class SoftwareDeveloperBuilder implements SkillsBuilder{
    private SoftwareEngineer softwareEngineer;

    public SoftwareDeveloperBuilder()   {
        this.softwareEngineer = new SoftwareEngineer();
    }

    public SkillsBuilder setJavaSkill(int java){
        this.softwareEngineer.setJava(java);
        return this;
    }
    public SkillsBuilder setDSASkill(int dsa){
        this.softwareEngineer.setDSA(dsa);
        return this;
    }
    public SkillsBuilder setSeleniumSkill(int selenium){
        this.softwareEngineer.setSelenium(selenium);
        return this;
    }
    public SkillsBuilder setSpringBootSkill(int springBoot){
        this.softwareEngineer.setSpringBoot(springBoot);
        return this;
    }
    public SkillsBuilder setAWSSkill(int aws){
        this.softwareEngineer.setAWS(aws);
        return this;
    }
    public SkillsBuilder setReactSkill(int react){
        this.softwareEngineer.setReact(react);
        return this;
    }

    public SoftwareEngineer getSoftwareEngineer(){
        return this.softwareEngineer;
    }
}

class Client {
    public static void main(String[] args)  {
        SkillsBuilder backendDeveloperBuilder = new SoftwareDeveloperBuilder();
        SoftwareEngineer backendDeveloper = backendDeveloperBuilder.setJavaSkill(8).setSpringBootSkill(7).setDSASkill(9).setAWSSkill(5).getSoftwareEngineer();

        SkillsBuilder frontendDeveloperBuilder = new SoftwareDeveloperBuilder();
        SoftwareEngineer frontendDeveloper = frontendDeveloperBuilder.setReactSkill(8).setDSASkill(7).setAWSSkill(5).getSoftwareEngineer();

        SkillsBuilder devOpsBuilder = new SoftwareDeveloperBuilder();
        SoftwareEngineer devOps = devOpsBuilder.setDSASkill(6).setAWSSkill(9).getSoftwareEngineer();

        SkillsBuilder testerBuilder = new SoftwareDeveloperBuilder();
        SoftwareEngineer tester = testerBuilder.setSeleniumSkill(9).setDSASkill(7).setJavaSkill(7).setAWSSkill(5).getSoftwareEngineer();

        backendDeveloper.showSkillsDetails("BackendDeveloper");
        devOps.showSkillsDetails("DevOps");
        frontendDeveloper.showSkillsDetails("FrontendDeveloper");
        tester.showSkillsDetails("Tester");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Factory Method Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt; - Defines an interface for creating an object, but lets subclasses alter the type of objects that will be created.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why/When to use&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Polymorphism and Extensibility&lt;/u&gt;: When you want to provide a way for subclasses to determine the type of objects they create, use the Factory Method pattern to promote polymorphism and extensibility.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Decoupling&lt;/u&gt;: If you need to decouple the client code from the specific class being instantiated, Factory Methods provide a level of indirection.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Configurability&lt;/u&gt;: When you want to allow clients to configure the objects they create by providing parameters or options, the Factory Method pattern is helpful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Flexibility&lt;/u&gt;: Allows subclasses to determine the type of objects that will be created, promoting flexibility in object creation.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Polymorphism&lt;/u&gt;: Supports polymorphism by returning objects of a common interface, making it easy to work with different implementations.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Separation of Concerns&lt;/u&gt;: Decouples the client code from the concrete class being instantiated, improving maintainability and testability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8yu2vrk1jybij01f38oh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8yu2vrk1jybij01f38oh.jpg" alt="Factory UML"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Profession {
    void print();
}

class Teacher implements Profession{
    public void print() {
        System.out.println("In Print of Teacher class");
    }
}

class Doctor implements Profession{
    public void print() {
        System.out.println("In Print of Doctor class");
    }
}

class ProfessionFactory {
    public Profession getProfession(String typeOfProfession){
        Profession prof=null;
          if(typeOfProfession.equalsIgnoreCase("Doctor")){
              prof=new Doctor();
          }else if(typeOfProfession.equalsIgnoreCase("Teacher")){
              prof=new Teacher();
          }
          return prof;
       }
}

public class Client {
    public static void main(String[] args) {
        ProfessionFactory professionFactory = new ProfessionFactory();
        Profession doc = professionFactory.getProfession("Doctor");
        doc.print();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Abstract Factory Method Design Pattern :
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt; - Provides an interface for creating families of related or dependent objects without specifying their concrete classes. It allows you to create sets of related objects with a consistent interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why/When to use&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Creating Object Families&lt;/u&gt;: Use the Abstract Factory pattern when you need to create families of related or dependent objects while ensuring that they work together cohesively.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Consistency Across Objects&lt;/u&gt;: When you want to ensure that the objects created by the factory have a consistent interface or adhere to a common theme, the Abstract Factory is ideal.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Adapting to Multiple Implementations&lt;/u&gt;: If you anticipate needing to switch between different implementations of related objects (e.g., different UI components), the Abstract Factory supports this flexibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt; - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Family of Objects&lt;/u&gt;: Creates families of related or dependent objects while ensuring consistency across them.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Encapsulation&lt;/u&gt;: Encapsulates the details of object creation, providing an abstract interface for creating objects.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Configurable&lt;/u&gt;: Allows easy switching between different sets of related objects by changing the concrete factory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UML&lt;/strong&gt; - &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpf1rilw8fkz5b4snhv83.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpf1rilw8fkz5b4snhv83.jpg" alt="Abstract Factory Method UML"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.lang.RuntimeException;

interface Car{
    void startCar();
}

class Tata implements Car{
    public void startCar(){
        System.out.println("Tata Car Started");
    }
}

class Maruti implements Car{
    public void startCar(){
        System.out.println("Maruti Car Started");
    }
}

interface Bike{
    void startBike();
}

class Hero implements Bike{
    public void startBike(){
        System.out.println("Tata Car Started");
    }
}

class Honda implements Bike{
    public void startBike(){
        System.out.println("Maruti Car Started");
    }
}

interface VehicleFactory{
    Car getCar(String carType);
    Bike getBike(String bikeType);
}

class CarFactory implements VehicleFactory{
    public Car getCar(String carType){
        if(carType.equalsIgnoreCase("Tata")){
            return new Tata();
        }else if(carType.equalsIgnoreCase("Maruti")){
            return new Maruti();
        }else{
            throw new RuntimeException(carType + " Car does not exist");
        }
    }
    public Bike getBike(String bikeType){
        throw new RuntimeException(bikeType + " is not manufactured in CarFactory");
    }
}

class BikeFactory implements VehicleFactory{
    public Car getCar(String carType){
        throw new RuntimeException(carType + " is not manufactured in BikeFactory");
    }
    public Bike getBike(String bikeType){
        if(bikeType.equalsIgnoreCase("Hero")){
            return new Hero();
        }else if(bikeType.equalsIgnoreCase("Honda")){
            return new Honda();
        }else{
            throw new RuntimeException(bikeType + " Bike does not exist");
        }
    }
}

class AbstractFactoryCreator{
    public VehicleFactory getFactory(String factoryType){
        if(factoryType.equalsIgnoreCase("Car")){
            return new CarFactory();
        }else if(factoryType.equalsIgnoreCase("Bike")){
            return new BikeFactory();
        }else{
            throw new RuntimeException(factoryType + " Factory does not exist");
        }
    }
}

public class Client{
    public static void main (String[] args) {
        AbstractFactoryCreator abstractFactoryCreator = new AbstractFactoryCreator();
        VehicleFactory vehicleFactory = abstractFactoryCreator.getFactory("car");

        Car myCar = vehicleFactory.getCar("tata");
        myCar.startCar();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;In conclusion, Creational Design Patterns provide essential tools for efficient, maintainable, and adaptable software. Choose patterns wisely to create robust solutions. Happy coding!&lt;br&gt;
I hope you found my blog enjoyable and informative.&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>lowleveldesign</category>
      <category>oops</category>
      <category>java</category>
    </item>
  </channel>
</rss>
