Determine the different ways the system will be used. This includes main functions the system needs to perform and who will use it.
1) Each User can open an account as user and only members who are part of streaming service will crate the account as admin
2) Admin can add new movies
3) User can stream the required movies in the quality and language they want
4) User can only watch movie if he is subscribed to the service
5) User can use different payment methods to buy the subscription
6) User can pay by upi , card or netbanking
7) User can serach for the desired movies by name, actors, type
Based on the requirements and use cases, identify the main objects of the system...
Core Objects
Account
User
Admin
Subscription Service
SubscriptionService
PaymentService
PaymentByUpi
PaymentByCard
VideoStreamingService
Recommendataion Service
Recommendataion by Name
Recommendataion by Actors
Video
VideoItem
Determine how these objects will interact with each other to fulfill the use cases...
Account class is parent class of user and admin class
SubscriptionService Service has payment Service for managing the payment for the user
VideoStreamingService has VideoItem
VideoItem has Video
Payment Service has payMentByCard, PaymentBy Upi
Recommendataion by name, Recommendataion by actors implement recomendation Servcie
Design inheritance trees where applicable to promote code reuse and polymorphism. This step involves identifying common attributes and behaviors that can be abstracted into parent classes...
Consider using design patterns (e.g., Factory, Singleton, Observer, Strategy) that fit the problem...
The design will be using strategy design pattern for the stategy of payment and recomendation
The design is using factory method when creating user and admin
The design will be using singleton pattern for creating single instacne of video streaming service
Attributes: For each class, define the attributes (data) it will hold...
Methods: Define the methods (functions) that operate on the attributes. Ensure they align with the object's responsibilities and adhere to the principle of encapsulation.
import java.util.*;
import java.util.stream.Collectors;
// Base Account Class
class Account {
private static int idCounter = 0;
private final String accountId;
private String firstName;
private String lastName;
public Account(String firstName, String lastName) {
this.accountId = "ACC" + (++idCounter);
this.firstName = firstName;
this.lastName = lastName;
}
public String getAccountId() {
return accountId;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
// Admin Class
class Admin extends Account {
public Admin(String firstName, String lastName) {
super(firstName, lastName);
}
}
// User Class
class User extends Account {
public User(String firstName, String lastName) {
super(firstName, lastName);
}
}
// Video Class
class Video {
private String movieName;
private String actorName;
private String type;
public Video(String movieName, String actorName, String type) {
this.movieName = movieName;
this.actorName = actorName;
this.type = type;
}
public String getMovieName() {
return movieName;
}
public String getActorName() {
return actorName;
}
public String getType() {
return type;
}
@Override
public String toString() {
return "Movie: " + movieName + ", Actor: " + actorName + ", Type: " + type;
}
}
// Input Utility Class
class InputUtil {
private static final Scanner scanner = new Scanner(System.in);
public static int getIntInput(String prompt, String errorMessage) {
while (true) {
try {
System.out.print(prompt);
return Integer.parseInt(scanner.nextLine().trim());
} catch (NumberFormatException e) {
System.out.println(errorMessage);
}
}
}
public static String getStringInput(String prompt, String errorMessage) {
while (true) {
System.out.print(prompt);
String input = scanner.nextLine().trim();
if (!input.isEmpty()) {
return input;
}
System.out.println(errorMessage);
}
}
}
// Payment Service Interface
interface PaymentService {
void makePayment(int amount);
}
// Payment Implementations
class PaymentByUpi implements PaymentService {
public void makePayment(int amount) {
System.out.println("Payment of $" + amount + " made using UPI.");
}
}
class PaymentByCard implements PaymentService {
public void makePayment(int amount) {
System.out.println("Payment of $" + amount + " made using Card.");
}
}
// Subscription Service
class SubscriptionService {
private Set<String> subscribedUsers = new HashSet<>();
public boolean hasSubscription(Account account) {
return subscribedUsers.contains(account.getAccountId());
}
public void addSubscription(Account account) {
System.out.println("Select Payment Method:");
System.out.println("1 -> Payment by UPI");
System.out.println("2 -> Payment by Card");
int choice = InputUtil.getIntInput("Enter choice: ", "Invalid input. Please enter 1 or 2.");
PaymentService paymentService = (choice == 1) ? new PaymentByUpi() : new PaymentByCard();
paymentService.makePayment(100);
subscribedUsers.add(account.getAccountId());
System.out.println("Subscription added successfully for " + account.getFirstName() + " " + account.getLastName());
}
}
// Video Service
class VideoService {
private List<Video> videos = new ArrayList<>();
public void addVideo(Admin admin, Video video) {
if (admin == null) {
throw new IllegalArgumentException("Only admins can add videos.");
}
videos.add(video);
System.out.println("Movie added successfully: " + video.getMovieName());
}
public List<Video> searchMovies(String keyword) {
return videos.stream()
.filter(v -> v.getMovieName().toLowerCase().contains(keyword.toLowerCase())
|| v.getActorName().toLowerCase().contains(keyword.toLowerCase())
|| v.getType().toLowerCase().contains(keyword.toLowerCase()))
.collect(Collectors.toList());
}
public List<Video> getVideos() {
return videos;
}
}
// Streaming Service
class StreamingService {
private VideoService videoService;
private SubscriptionService subscriptionService;
public StreamingService(VideoService videoService, SubscriptionService subscriptionService) {
this.videoService = videoService;
this.subscriptionService = subscriptionService;
}
public void streamMovie(User user) {
if (!subscriptionService.hasSubscription(user)) {
System.out.println("You do not have a subscription.");
subscriptionService.addSubscription(user);
}
System.out.println("Available Movies:");
List<Video> videos = videoService.getVideos();
if (videos.isEmpty()) {
System.out.println("No movies available at the moment.");
return;
}
for (int i = 0; i < videos.size(); i++) {
System.out.println((i + 1) + ". " + videos.get(i));
}
int choice = InputUtil.getIntInput("Select a movie number to stream: ", "Invalid input.");
Video selectedVideo = videos.get(choice - 1);
String quality = InputUtil.getStringInput("Enter video quality (e.g., HD, 4K): ", "Quality cannot be empty.");
String language = InputUtil.getStringInput("Enter preferred language: ", "Language cannot be empty.");
System.out.println("Streaming " + selectedVideo.getMovieName() + " in " + quality + " quality and " + language + " language...");
}
}
// Main Class
public class Main {
public static void main(String[] args) {
VideoService videoService = new VideoService();
SubscriptionService subscriptionService = new SubscriptionService();
StreamingService streamingService = new StreamingService(videoService, subscriptionService);
// Demo Admin and User
Admin admin = new Admin("John", "Doe");
User user = new User("Jane", "Smith");
// Admin adds movies
videoService.addVideo(admin, new Video("Inception", "Leonardo DiCaprio", "Sci-Fi"));
videoService.addVideo(admin, new Video("Titanic", "Leonardo DiCaprio", "Romance"));
// User streams a movie
streamingService.streamMovie(user);
// User searches for movies
String keyword = InputUtil.getStringInput("Search for movies by name, actor, or type: ", "Search term cannot be empty.");
List<Video> searchResults = videoService.searchMovies(keyword);
if (searchResults.isEmpty()) {
System.out.println("No movies found matching your search.");
} else {
searchResults.forEach(System.out::println);
}
}
}
Check and explain whether your design adheres to solid principles (Ask interviewer what SOLID principle is if you can not recall it.)...
Single Responsibility Principle- > Each class is having only one function
Open and closed principle -> we are following open and closed and principle in account, user and admin class
Liskov substitution Principle -> User and admin can be substitued in place of account causing no harm to exisitnig functionalities
Interface segration principle -> Payment by upi, card will only implement the payment method which is defined in the interface
Dependency inversion principle -> Insted of hardCoding the implemented class we are using base interface for the implementation
Explain how your design can handle changes in scale and whether it would be easily to extend with new functionalities...
As we are using solid principles the design principles and design pattern the design is easily scalalbe
Try creating a class, flow, state and/or sequence diagram using the diagramming tool. Mermaid flow diagrams can be used to represent system use cases. You can ask the interviewer bot to create a starter diagram if unfamiliar with the tool. Briefly explain your diagrams if necessary...
Created class diagram
Critically examine your design for any flaws or areas for future improvement...
Add machine learning algorithms to provide users with better suggestions.