Design (LLD)  a Bar Graph Library - Machine Coding

Design (LLD) a Bar Graph Library - Machine Coding

My project.png

Bar Graph Library - Part 1

  1. 2-D Graph with (x, y axis)

  2. Uniform Range (like value will be in multiple or will have same difference)

  3. Each Bar Can have Two Colors (both can be anything but same for all bars)

  4. Values can be Added dynamic (it can be real time also)

Features

  1. Generate 2D Graph

  2. Create Bar with specific color

  3. Render the 2d graph using the given bars values

Rough Solution (LLD-Machine Coding)

// Axis class using Builder Pattern
class Axis {
    private int base;
    private int range;

    private Axis(Builder builder) {
        this.base = builder.base;
        this.range = builder.range;
    }

    public static class Builder {
        private int base;
        private int range;

        public Builder setBase(int base) {
            this.base = base;
            return this;
        }

        public Builder setRange(int range) {
            this.range = range;
            return this;
        }

        public Axis build() {
            return new Axis(this);
        }
    }
}

// 2D Graph using Composite Pattern
interface GraphComponent {
    void render();
}

class Bar extends Element implements GraphComponent {
    private int width;
    private int height;

    public Bar(String color, int width, int height) {
        super(color);
        this.width = width;
        this.height = height;
    }

    @Override
    public void render() {
        System.out.println("Drawing bar with width " + width + " and height " + height + " in color " + getColor());
    }
}

// BarGraph with Composite Pattern and Strategy Pattern for rendering
class BarGraph implements GraphComponent {
    private List<GraphComponent> bars = new ArrayList<>();

    public void addBar(GraphComponent bar) {
        bars.add(bar);
    }

    @Override
    public void render() {
        for (GraphComponent bar : bars) {
            bar.render();
        }
    }
}

// Element class
abstract class Element {
    private String color;

    public Element(String color) {
        this.color = color;
    }

    public String getColor() {
        return color;
    }
}

// Renderer interface using Strategy Pattern
interface Renderer {
    void renderGraph(BarGraph graph);
}

// Concrete renderer using Strategy Pattern
class SimpleRenderer implements Renderer {
    @Override
    public void renderGraph(BarGraph graph) {
        System.out.println("Rendering Bar Graph in Simple mode.");
        graph.render();
    }
}

// Factory Method for creating bars
class BarFactory {
    public static Bar createBar(String color, int width, int height) {
        return new Bar(color, width, height);
    }
}

// Main class to demonstrate usage
public class Main {
    public static void main(String[] args) {
        // Using Builder to create axes
        Axis xAxis = new Axis.Builder().setBase(0).setRange(10).build();
        Axis yAxis = new Axis.Builder().setBase(0).setRange(100).build();

        // Using Factory Method to create bars
        Bar bar1 = BarFactory.createBar("red", 5, 50);
        Bar bar2 = BarFactory.createBar("blue", 4, 70);

        // Using Composite Pattern to add bars to graph
        BarGraph barGraph = new BarGraph();
        barGraph.addBar(bar1);
        barGraph.addBar(bar2);

        // Using Strategy Pattern to render graph
        Renderer renderer = new SimpleRenderer();
        renderer.renderGraph(barGraph);
    }
}

🔴 Key Issues in the Design:

1. Concurrency Problems - The graph allows dynamic updates, but there's no thread safety for real-time data additions. What happens when multiple threads update the graph? Race conditions!
2. Lack of Extensibility - The design doesn’t support animations, interactivity, or different bar styles. A well-designed system should allow easy feature additions without modifying core components (Open-Closed Principle!).
3. Inefficient Rendering Strategy - The current SimpleRenderer renders everything at once. What if we have thousands of bars? The system should use Batch Rendering or Lazy Loading.
4. Tight Coupling Between Components - Bar creation depends on a factory, but what if we need different bar styles? Shouldn’t we have an Abstract Factory or a Prototype Pattern to clone similar bars efficiently?
5. No Event-Driven Updates - Instead of polling for data, an Observer Pattern could notify the graph when new values arrive, making it real-time friendly.

Solution of Above mentioned issues will be covered in our Premium course.