📂
Interview Prep
LLD Questions
LLD Questions
  • LLD Introduction
  • Meeting Scheduler
  • Distributed Cache System
  • Rate limiter
  • Multi-Tier Elevator System
  • MyGate System
  • Uber Sytem LLD
  • Parking Lot System
  • Online book store
  • Library Management System
  • Movie Ticket Booking System
  • Hotel Management System
  • File Storage System
    • Solution 2
  • Chat Application
  • Social Media Platform
  • Notification System
  • Airline Reservation System
  • ATM System
  • E-commerce Website
  • Food Delivery System
  • Shopping Cart System
  • URL Shortener system
  • Chess Tournament System
  • Threading therory
  • OOP questions
Powered by GitBook
On this page
  • Key Design Patterns Used
  • System Components & Patterns
  • 1. File Metadata (Builder Pattern)
  • 2. File Storage Service (Strategy + Factory + Singleton)
  • 3. File Sharing Service (Observer Pattern)
  • 4. Access Control (Proxy Pattern)
  • Summary of Patterns Used
  1. File Storage System

Solution 2

Designing a Google Drive-like file storage system requires not only scalability and modularity but also the use of appropriate design patterns to ensure maintainability, flexibility, and performance.


Key Design Patterns Used

Pattern

Usage in File Storage System

Singleton

Ensures a single instance of services like AuthService and FileStorageService.

Factory Pattern

Creates objects for different storage backends (Local, AWS S3, Google Cloud Storage).

Strategy Pattern

Allows switching storage mechanisms dynamically (Local, Cloud, Distributed FS).

Observer Pattern

Notifies users when a file is shared with them.

Decorator Pattern

Adds functionalities like compression and encryption to file storage.

Proxy Pattern

Restricts direct access to storage and adds logging/security.

Builder Pattern

Constructs complex file metadata objects step by step.


System Components & Patterns

  1. File Metadata (Builder Pattern)

  2. File Storage Service (Strategy, Factory, Singleton)

  3. File Sharing Service (Observer)

  4. Authentication Service (Singleton)

  5. Access Proxy (Proxy Pattern)

  6. Compression/Encryption for File Upload (Decorator Pattern)


1. File Metadata (Builder Pattern)

Used to construct complex metadata objects step by step.

public class FileMetadata {
    private final String fileId;
    private final String fileName;
    private final String fileType;
    private final long fileSize;
    private final String ownerId;
    private final String storagePath;

    private FileMetadata(FileMetadataBuilder builder) {
        this.fileId = builder.fileId;
        this.fileName = builder.fileName;
        this.fileType = builder.fileType;
        this.fileSize = builder.fileSize;
        this.ownerId = builder.ownerId;
        this.storagePath = builder.storagePath;
    }

    public static class FileMetadataBuilder {
        private String fileId;
        private String fileName;
        private String fileType;
        private long fileSize;
        private String ownerId;
        private String storagePath;

        public FileMetadataBuilder setFileId(String fileId) {
            this.fileId = fileId;
            return this;
        }

        public FileMetadataBuilder setFileName(String fileName) {
            this.fileName = fileName;
            return this;
        }

        public FileMetadataBuilder setFileType(String fileType) {
            this.fileType = fileType;
            return this;
        }

        public FileMetadataBuilder setFileSize(long fileSize) {
            this.fileSize = fileSize;
            return this;
        }

        public FileMetadataBuilder setOwnerId(String ownerId) {
            this.ownerId = ownerId;
            return this;
        }

        public FileMetadataBuilder setStoragePath(String storagePath) {
            this.storagePath = storagePath;
            return this;
        }

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

2. File Storage Service (Strategy + Factory + Singleton)

  • Factory Pattern: Creates storage service based on type (Local, AWS, Google Cloud).

  • Strategy Pattern: Allows dynamic switching between storage mechanisms.

  • Singleton Pattern: Ensures only one instance of FileStorageService.

// Strategy Interface
public interface StorageStrategy {
    void storeFile(String fileName, byte[] data) throws IOException;
    byte[] retrieveFile(String fileName) throws IOException;
}

// Concrete Strategy 1: Local Storage
public class LocalStorageStrategy implements StorageStrategy {
    private static final String STORAGE_DIR = "local_storage/";

    @Override
    public void storeFile(String fileName, byte[] data) throws IOException {
        Files.write(Paths.get(STORAGE_DIR + fileName), data);
    }

    @Override
    public byte[] retrieveFile(String fileName) throws IOException {
        return Files.readAllBytes(Paths.get(STORAGE_DIR + fileName));
    }
}

// Concrete Strategy 2: Cloud Storage (AWS S3)
public class CloudStorageStrategy implements StorageStrategy {
    @Override
    public void storeFile(String fileName, byte[] data) {
        System.out.println("Uploading " + fileName + " to AWS S3...");
    }

    @Override
    public byte[] retrieveFile(String fileName) {
        System.out.println("Downloading " + fileName + " from AWS S3...");
        return new byte[0]; // Simulated response
    }
}

// Factory Pattern for Storage Selection
public class StorageFactory {
    public static StorageStrategy getStorageStrategy(String type) {
        if ("LOCAL".equalsIgnoreCase(type)) {
            return new LocalStorageStrategy();
        } else if ("CLOUD".equalsIgnoreCase(type)) {
            return new CloudStorageStrategy();
        }
        throw new IllegalArgumentException("Unknown storage type");
    }
}

// Singleton File Storage Service
public class FileStorageService {
    private static FileStorageService instance;
    private StorageStrategy storageStrategy;

    private FileStorageService(StorageStrategy strategy) {
        this.storageStrategy = strategy;
    }

    public static FileStorageService getInstance(StorageStrategy strategy) {
        if (instance == null) {
            instance = new FileStorageService(strategy);
        }
        return instance;
    }

    public void uploadFile(String fileName, byte[] data) throws IOException {
        storageStrategy.storeFile(fileName, data);
    }

    public byte[] downloadFile(String fileName) throws IOException {
        return storageStrategy.retrieveFile(fileName);
    }
}

3. File Sharing Service (Observer Pattern)

Used to notify users when a file is shared.

import java.util.ArrayList;
import java.util.List;

interface Observer {
    void update(String message);
}

class User implements Observer {
    private String name;

    public User(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + " received notification: " + message);
    }
}

class FileSharingService {
    private List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void shareFile(String fileId, String userName) {
        System.out.println("File " + fileId + " shared with " + userName);
        notifyObservers("File " + fileId + " shared with you.");
    }

    private void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

4. Access Control (Proxy Pattern)

Restricts unauthorized file access.

interface FileAccess {
    void accessFile(String fileName, String userId);
}

class RealFileAccess implements FileAccess {
    @Override
    public void accessFile(String fileName, String userId) {
        System.out.println(userId + " is accessing " + fileName);
    }
}

class FileAccessProxy implements FileAccess {
    private RealFileAccess realFileAccess;
    private boolean isAuthenticated;

    public FileAccessProxy(boolean isAuthenticated) {
        this.realFileAccess = new RealFileAccess();
        this.isAuthenticated = isAuthenticated;
    }

    @Override
    public void accessFile(String fileName, String userId) {
        if (isAuthenticated) {
            realFileAccess.accessFile(fileName, userId);
        } else {
            System.out.println("Access Denied for " + userId);
        }
    }
}

Summary of Patterns Used

  • Builder Pattern: Constructs file metadata.

  • Strategy Pattern: Supports multiple storage types.

  • Factory Pattern: Creates different storage backends.

  • Singleton Pattern: Ensures a single instance of services.

  • Observer Pattern: Sends notifications when files are shared.

  • Proxy Pattern: Restricts unauthorized file access.

  • Decorator Pattern: Can be used for adding compression/encryption.

PreviousFile Storage SystemNextChat Application

Last updated 2 months ago