Design (LLD) Amazon Prime Video - Machine Coding

Features Required :

  1. User Authentication:

    • Users should be able to create accounts, log in, and log out.
  2. Video Catalog:

    • The system should have a catalog of movies and TV shows with details like title, genre, release date, and duration.
  3. User Profile Management:

    • Users should be able to view and edit their profiles, including preferences, watch history, etc.
  4. Watchlist:

    • Users should be able to add/remove videos to/from their watchlist.
  5. Video Streaming:

    • Users should be able to stream videos.
  6. Recommendation System:

    • The system should provide personalized recommendations based on user preferences and watch history.
  7. User Reviews and Ratings:

    • Users should be able to rate and review videos.
  8. Subscription Management:

    • Users should be able to subscribe, and the system should enforce subscription rules.

Design Patterns and SOLID Principles:

  1. Singleton Pattern:

    • For the VideoCatalog to ensure a single point of access.
  2. Factory Method Pattern:

    • For creating different types of videos like movies and TV shows.
  3. Observer Pattern:

    • For notifying users about new releases, recommendations, etc.
  4. Strategy Pattern:

    • For different recommendation algorithms.
  5. Command Pattern:

    • For executing commands like adding/removing videos from the watchlist.
  6. Decorator Pattern:

    • For enhancing basic video objects with additional features.
  7. Composite Pattern:

    • For creating playlists that can contain both individual videos and other playlists.
  8. State Pattern:

    • For managing the state of a video (e.g., playing, paused, stopped).
  9. Proxy Pattern:

    • For controlling access to streaming videos based on user subscription.
  10. Dependency Inversion Principle (SOLID):

    • High-level modules (e.g., User Interface) should not depend on low-level modules but both should depend on abstractions.
  11. Open/Closed Principle (SOLID):

    • Classes should be open for extension but closed for modification.

Algorithm Involved:

  1. Recommendation Algorithm:

    • Algorithms for providing personalized recommendations based on user behavior and preferences.

Diagrams

Code:

class VideoCatalog {
    private static VideoCatalog instance;
    private List<Video> videos;

    private VideoCatalog() {
        videos = new ArrayList<>();
    }

    public static VideoCatalog getInstance() {
        if (instance == null) {
            instance = new VideoCatalog();
        }
        return instance;
    }

    public void addVideo(Video video) {
        videos.add(video);
    }

    public Video getVideo(String videoId) {
        for (Video video : videos) {
            if (video.getId().equals(videoId)) {
                return video;
            }
        }
        return null;
    }
}
interface VideoFactory {
    Video createVideo(String type, String title);
}

class MovieFactory implements VideoFactory {
    public Video createVideo(String title) {
        return new Movie(title);
    }
}

class TVShowFactory implements VideoFactory {
    public Video createVideo(String title) {
        return new TVShow(title);
    }
}
interface Observer {
    void update(String message);
}

class User implements Observer {
    private String userId;

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

    public void update(String message) {
        System.out.println("User " + userId + " received update: " + message);
    }
}
class VideoNotifier {
    private List<Observer> observers;

    public VideoNotifier() {
        observers = new ArrayList<>();
    }

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

    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}
interface RecommendationStrategy {
    List<Video> recommendVideos(User user);
}

class PopularVideosStrategy implements RecommendationStrategy {
    public List<Video> recommendVideos(User user) {
        // Implementation details...
        return null;
    }
}

class PersonalizedVideosStrategy implements RecommendationStrategy {
    public List<Video> recommendVideos(User user) {
        // Implementation details...
        return null;
    }
}
interface VideoCommand {
    void execute();
}

class AddToWatchlistCommand implements VideoCommand {
    private Video video;

    public AddToWatchlistCommand(Video video) {
        this.video = video;
    }

    public void execute() {
        video.addToWatchlist();
    }
}

class RemoveFromWatchlistCommand implements VideoCommand {
    private Video video;

    public RemoveFromWatchlistCommand(Video video) {
        this.video = video;
    }

    public void execute() {
        video.removeFromWatchlist();
    }
}
abstract class VideoDecorator implements Video {
    protected Video decoratedVideo;

    public VideoDecorator(Video decoratedVideo) {
        this.decoratedVideo = decoratedVideo;
    }

    public void play() {
        decoratedVideo.play();
    }
}

class SubtitledVideo extends VideoDecorator {
    public SubtitledVideo(Video decoratedVideo) {
        super(decoratedVideo);
    }

    public void play() {
        // Add subtitle logic...
        System.out.println("Playing subtitled video...");
        super.play();
    }
}

class HDVideo extends VideoDecorator {
    public HDVideo(Video decoratedVideo) {
        super(decoratedVideo);
    }

    public void play() {
        // Add HD quality logic...
        System.out.println("Playing HD video...");
        super.play();
    }
}
interface Playlist extends Video {
    void addVideo(Video video);

    void removeVideo(Video video);
}

class BasicPlaylist implements Playlist {
    private List<Video> videos;

    public BasicPlaylist() {
        videos = new ArrayList<>();
    }

    public void addVideo(Video video) {
        videos.add(video);
    }

    public void removeVideo(Video video) {
        videos.remove(video);
    }

    public void play() {
        System.out.println("Playing all videos in the playlist...");
        for (Video video : videos) {
            video.play();
        }
    }
}
interface VideoState {
    void play();

    void pause();

    void stop();
}

class PlayingState implements VideoState {
    public void play() {
        System.out.println("Video is already playing.");
    }

    public void pause() {
        System.out.println("Pausing video...");
    }

    public void stop() {
        System.out.println("Stopping video...");
    }
}

class PausedState implements VideoState {
    public void play() {
        System.out.println("Resuming video...");
    }

    public void pause() {
        System.out.println("Video is already paused.");
    }

    public void stop() {
        System.out.println("Stopping video...");
    }
}

class StoppedState implements VideoState {
    public void play() {
        System.out.println("Starting to play video...");
    }

    public void pause() {
        System.out.println("Cannot pause. Video is stopped.");
    }

    public void stop() {
        System.out.println("Video is already stopped.");
    }
}
interface Video {
    String getId();

    void play();
}

class StreamingVideo implements Video {
    private String videoId;

    public StreamingVideo(String videoId) {
        this.videoId = videoId;
    }

    public String getId() {
        return videoId;
    }

    public void play() {
        System.out.println("Playing streaming video " + videoId + "...");
    }
}

class VideoProxy implements Video {
    private Video video;
    private User user;

    public VideoProxy(Video video, User user) {
        this.video = video;
        this.user = user;
    }

    public String getId() {
        return video.getId();
    }

    public void play() {
        if (userHasSubscription()) {
            video.play();
        } else {
            System.out.println("User " + user.getId() + " does not have a subscription.");
        }
    }

    private boolean userHasSubscription() {
        // Check user subscription status...
        return true;
    }
}
class Movie implements Video {
    private String title;

    public Movie(String title) {
        this.title = title;
    }

    public String getId() {
        return title.replaceAll("\\s", "_");
    }

    public void play() {
        System.out.println("Playing movie: " + title);
    }

    public void addToWatchlist() {
        System.out.println("Added movie " + title + " to watchlist.");
    }

    public void removeFromWatchlist() {
        System.out.println("Removed movie " + title + " from watchlist.");
    }
}
class TVShow implements Video {
    private String title

;

    public TVShow(String title) {
        this.title = title;
    }

    public String getId() {
        return title.replaceAll("\\s", "_");
    }

    public void play() {
        System.out.println("Playing TV show: " + title);
    }

    public void addToWatchlist() {
        System.out.println("Added TV show " + title + " to watchlist.");
    }

    public void removeFromWatchlist() {
        System.out.println("Removed TV show " + title + " from watchlist.");
    }
}
class AmazonPrimeVideo {
    public static void main(String[] args) {
        // Implementation details...
        User user1 = new User("user1");
        User user2 = new User("user2");

        VideoCatalog videoCatalog = VideoCatalog.getInstance();

        Video movie = new Movie("Inception");
        Video tvShow = new TVShow("Breaking Bad");

        videoCatalog.addVideo(movie);
        videoCatalog.addVideo(tvShow);

        VideoNotifier videoNotifier = new VideoNotifier();
        videoNotifier.addObserver(user1);
        videoNotifier.addObserver(user2);

        videoNotifier.notifyObservers("New video available!");

        RecommendationStrategy strategy = new PopularVideosStrategy();
        List<Video> recommendations = strategy.recommendVideos(user1);
        System.out.println("Recommendations for user1: " + recommendations);

        VideoCommand addToWatchlistCommand = new AddToWatchlistCommand(movie);
        addToWatchlistCommand.execute();

        VideoCommand removeFromWatchlistCommand = new RemoveFromWatchlistCommand(tvShow);
        removeFromWatchlistCommand.execute();

        VideoDecorator subtitledMovie = new SubtitledVideo(movie);
        subtitledMovie.play();

        VideoDecorator hdTvShow = new HDVideo(tvShow);
        hdTvShow.play();

        Playlist playlist = new BasicPlaylist();
        playlist.addVideo(movie);
        playlist.addVideo(tvShow);
        playlist.play();

        VideoState playingState = new PlayingState();
        playingState.play();
        playingState.pause();
        playingState.stop();

        Video video = new StreamingVideo("xyz123");
        VideoProxy videoProxy = new VideoProxy(video, user1);
        videoProxy.play();
    }
}

This contains a basic implementation of the Amazon Prime Video system with explanations of design patterns and principles used. Adjustments and additional implementations can be made based on specific requirements and features.

Did you find this article valuable?

Support Subhahu Jain by becoming a sponsor. Any amount is appreciated!