Bea.AI design blog
  • System design algorithms
    • Consistant Hashing, Bloom Filter, SkipLists, B-Tree, LRU/LFU
    • Reverse index, Inverted index, Trie, Rsync, Merkle tree
    • Leaky bucket/Token bucket, GeoHash, Quadtree, Leader election, Consensus
    • Time sync, Erasure coding, Message digest, Atomic commit, Mutual exclusion
    • Global state collection, Gossip, Replica management, Self-stabilization, HyperLoglog
    • Count-min Sketch, Hierarchial timing, Operational transform, Last write Wins, Vector clocks
  • Systems design
    • Metrics monitor & alart system
    • API gateway
    • Distributed Key-Value Storage
    • Distributed notification system
    • Task Scheduler
    • Elevator System
  • General Design Templates
    • System Design Blueprint
  • Design topics
    • Topics 1
    • Topics 2
    • Topics 3
    • Topics 4
    • Topics 5
    • Topics 6
    • Topics 7
    • Topics 8
    • Topics 9
    • Topics 10
    • Topics 11
    • Topics 12
    • Topics 13
    • Topics 14
    • Topics 15
    • Topics 16
    • Topics 17
    • Topics 18
    • Topics 19
    • Topics 20
    • Topics 21
    • Topics 22
    • Topics 23
  • System design interview steps & template
  • Typical systems and tips
  • Behaviour Questions
  • Roles requirement
    • SDE-traffic-apple
    • SDE-tools-linkedin
  • Common Systems to use in system design
    • Kafka
    • Flink
    • InfluxDB & Prometheus
    • Kubernetes & Docker
    • Zoomkeeper & Etcd
    • Redis
    • Distributed transaction
  • Design Patterns and Use Scenarios
    • Pattern to creating objects
    • Object Assembling
    • Object Interaction / Responsibility
  • Micro-service network / Gateway
    • Basic concept
    • Performance analysis & optimization
    • Open source techs
  • Systems
    • Distributed Priority Queue
    • Design a Live Video Streaming Platform
Powered by GitBook
On this page
  • Singleton
  • Prototype
  • Builder
  • Factory
  • AbstractFactory
  1. Design Patterns and Use Scenarios

Pattern to creating objects

Singleton

This pattern is used to ensure only one instant exists.

class SingleTon {
  private static SingleTon instance;

  private SingleTon() {
  }

  public static SingleTon getInstance() {
    if (instance == null) {
      synchronized(SingleTon.class) {
        if (instance == null) {
          instance = new SingleTon();
        }
      }
    }
    return instance;
  }
}

class SingleTon2 {
  private static SingleTon2 singleton = new SingleTon2();
  private SingleTon2() {
    
  }
  public static SingleTon2 getInstance() {
    return singleton;
  }
}

public class Main {
    public static void main(String[] args) {
        // Get the singleton instance
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        // Both references point to the same instance
        System.out.println(singleton1 == singleton2); // Output: true
    }
}

Prototype

Clones instances for a prototypical instance.

// Prototype interface
interface Prototype {
    Prototype clone();
}

// Concrete prototype
class Circle implements Prototype {
    private int radius;

    public Circle(int radius) {
        this.radius = radius;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    @Override
    public Prototype clone() {
        return new Circle(this.radius);
    }

    @Override
    public String toString() {
        return "Circle with radius " + radius;
    }
}

// Client code
public class Main {
    public static void main(String[] args) {
        // Create a prototype instance
        Circle prototypeCircle = new Circle(5);

        // Clone the prototype to create new instances
        Circle circle1 = (Circle) prototypeCircle.clone();
        Circle circle2 = (Circle) prototypeCircle.clone();

        // Modify the cloned instances
        circle1.setRadius(10);
        circle2.setRadius(15);

        // Output the cloned instances
        System.out.println(circle1); // Output: Circle with radius 10
        System.out.println(circle2); // Output: Circle with radius 15
    }
}

Builder

Construct object step by step.

// Product class
class Product {
    private String property1;
    private String property2;
    // Other properties...

    // Private constructor to prevent instantiation from outside the class
    private Product(Builder builder) {
        this.property1 = builder.property1;
        this.property2 = builder.property2;
        // Set other properties...
    }

    // Getters for properties...
    
    // Builder class
    static class Builder {
        // Required parameters
        private String property1;
        private String property2;
        // Other optional parameters...

        // Constructor with required parameters
        public Builder(String property1, String property2) {
            this.property1 = property1;
            this.property2 = property2;
        }

        // Setter methods for optional parameters
        public Builder setProperty1(String property1) {
            this.property1 = property1;
            return this;
        }

        public Builder setProperty2(String property2) {
            this.property2 = property2;
            return this;
        }

        // Other setter methods for optional parameters...

        // Build method to create the Product object
        public Product build() {
            return new Product(this);
        }
    }
}

// Example usage
public class Main {
    public static void main(String[] args) {
        // Create a Product using the Builder
        Product product = new Product.Builder("value1", "value2")
                            .setProperty1("updatedValue1")
                            // .setProperty2("updatedValue2") // Optionally set other properties
                            .build();

        // Use the created Product
        System.out.println(product.getProperty1());
        System.out.println(product.getProperty2());
    }
}

Factory

Delegate object instantiation to subclasses.

// Interface for the product
interface Shape {
    void draw();
}

// Concrete implementations of the product
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

// Factory class to create objects of the product
class ShapeFactory {
    // Method to create objects based on input
    public static Shape createShape(String shapeType) {
        if (shapeType.equalsIgnoreCase("circle")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("rectangle")) {
            return new Rectangle();
        } else {
            throw new IllegalArgumentException("Invalid shape type: " + shapeType);
        }
    }
}

// Client code to use the factory to create objects
public class Main {
    public static void main(String[] args) {
        Shape circle = ShapeFactory.createShape("circle");
        Shape rectangle = ShapeFactory.createShape("rectangle");

        circle.draw(); // Output: Drawing a circle
        rectangle.draw(); // Output: Drawing a rectangle
    }
}

AbstractFactory

Creates related object families without specifying their concrete classes.

// Abstract Product A
interface Shape {
    void draw();
}

// Concrete Product A1
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

// Concrete Product A2
class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

// Abstract Product B
interface Color {
    void fill();
}

// Concrete Product B1
class Red implements Color {
    @Override
    public void fill() {
        System.out.println("Filling with red color");
    }
}

// Concrete Product B2
class Blue implements Color {
    @Override
    public void fill() {
        System.out.println("Filling with blue color");
    }
}

// Abstract Factory
interface AbstractFactory {
    Shape createShape();
    Color createColor();
}

// Concrete Factory 1
class ShapeColorFactory implements AbstractFactory {
    @Override
    public Shape createShape() {
        return new Circle();
    }

    @Override
    public Color createColor() {
        return new Red();
    }
}

// Concrete Factory 2
class ShapeColorFactory2 implements AbstractFactory {
    @Override
    public Shape createShape() {
        return new Rectangle();
    }

    @Override
    public Color createColor() {
        return new Blue();
    }
}

// Client code
public class Main {
    public static void main(String[] args) {
        // Create a factory instance
        AbstractFactory factory = new ShapeColorFactory();

        // Create products using the factory
        Shape shape = factory.createShape();
        Color color = factory.createColor();

        // Use the products
        shape.draw(); // Output: Drawing a circle
        color.fill(); // Output: Filling with red color
    }
}
PreviousDesign Patterns and Use ScenariosNextObject Assembling

Last updated 1 year ago