Bird
Raised Fist0

Design a Social Media Profile System - User, Follow, Post, Like, Feed OOP

LLDhardInterview freq: high
Choose your preparation mode4 modes available
🏗️
Design a Social Media Profile System - User, Follow, Post, Like, Feed OOP
Design a scalable, extensible social media profile system with user relationships, posts, likes, and personalized feeds using Java OOP principles.
hardSocial and Professional PlatformsFreq: high
Prerequisites:Tree Data StructureOOP DesignJava Concurrency Basics
⚙️
Functional Requirements
  • Users can follow and unfollow other users
  • Users can create posts with text content
  • Users can like and unlike posts
  • Feed shows posts from followed users sorted by timestamp
  • Feed generation must be efficient and scalable
  • Likes count must be consistent under concurrent updates
  • Follow relationships must prevent duplicates and race conditions
👤
Use Cases
  • User creates a profile
  • User follows/unfollows another user
  • User creates a post
  • User likes/unlikes a post
  • User views personalized feed
🧑‍💻
Actors
  • User
  • System Administrator
  • Feed Generator Service
❓
Clarifying Questions to Ask
  • What is the expected concurrency level for likes and follows? (e.g., thousands of concurrent threads)
  • Should the feed be generated on-demand or precomputed?
  • Is there a pricing strategy or rate limiting for API calls?
  • How to handle edge cases like circular follows or self-follow?
  • Should the system support private profiles or only public ones?
Out of Scope
✗ Commenting on posts
✗ Post sharing or reposting
✗ Media attachments (images/videos)
✗ Notification system
✗ Search functionality
🔢
Enumerations
enum PostVisibility
PUBLIC | PRIVATE | FRIENDS_ONLY
Defines visibility scope of posts to enforce access control; enum prevents typo bugs and enables exhaustive switch statements.
enum LikeStatus
LIKED | UNLIKED
Represents the state of a like action; using enum avoids magic strings and supports clear state transitions.
enum FollowStatus
FOLLOWING | NOT_FOLLOWING
Tracks follow relationship state; enum ensures type safety and clear semantics.
📦
User
5 fields
private final String userIdprivate String usernameprivate volatile Set<String> followersprivate volatile Set<String> followingprivate final List<Post> posts
Represents a social media user, manages follow relationships and posts authored by the user.
Why thisUsing Java class with synchronized methods ensures thread safety for follow and post operations.
Why notAvoided using external libraries or frameworks to keep design focused on core Java concurrency and OOP.
public synchronized boolean followUser(User userToFollow)Atomically adds userToFollow to this user's following set and adds this user to userToFollow's followers set.
public synchronized boolean unfollowUser(User userToUnfollow)Atomically removes userToUnfollow from this user's following set and removes this user from userToUnfollow's followers set.
public synchronized Post createPost(String content, PostVisibility visibility)Creates a new post authored by this user with specified content and visibility.
public List<Post> getFeed()Returns a list of posts from users this user follows, sorted by timestamp descending.
📦
Post
7 fields
private final String postIdprivate final String authorIdprivate final String contentprivate final long timestampprivate final PostVisibility visibilityprivate final AtomicInteger likeCountprivate final Set<String> likedUserIds
Represents a user-generated post with content, visibility, and like tracking.
Why thisAtomicInteger and synchronized methods ensure thread-safe like count updates.
Why notAvoided using external caching or NoSQL for likes to keep design simple and focused on concurrency.
public synchronized boolean likePost(String userId)Adds a like from userId if not already liked; increments likeCount atomically.
public synchronized boolean unlikePost(String userId)Removes a like from userId if previously liked; decrements likeCount atomically.
public int getLikeCount()Returns the current number of likes.
📦
FeedGenerator
1 fields
private final Map<String, User> userMap
Generates personalized feeds for users by aggregating posts from followed users.
Why thisCentralized feed generation allows efficient aggregation and sorting of posts.
Why notAvoided pushing feed updates to users to reduce complexity; opted for on-demand feed generation.
public List<Post> generateFeed(String userId)Fetches posts from users followed by userId, merges and sorts them by timestamp descending.
📦
FollowManager
2 fields
private final ConcurrentHashMap<String, Set<String>> followersMapprivate final ConcurrentHashMap<String, Set<String>> followingMap
Manages follow relationships with thread-safe operations to prevent duplicates and race conditions.
Why thisConcurrentHashMap and thread-safe sets ensure safe concurrent updates.
Why notAvoided database-level locking to reduce latency; concurrency handled in-memory.
public boolean follow(String followerId, String followeeId)Thread-safe method to add follow relationship if not already present.
public boolean unfollow(String followerId, String followeeId)Thread-safe method to remove follow relationship if present.
🔗
Relationships
User──►User[many-to-many]
associationindependent
User◆──►Post[one-to-many]
compositiondependent (Post lifecycle tied to User)
Post──►User[many-to-one]
associationindependent
User──►FeedGenerator[many-to-one]
associationindependent
FollowManager──►User[many-to-many]
associationindependent
🗄️
Users
PK: userId
userId STRING PRIMARY KEYusername STRINGfollowers SET<STRING>following SET<STRING>
Stores user profiles and their follow relationships.
🗄️
Posts
PK: postId
postId STRING PRIMARY KEYauthorId STRINGcontent TEXTtimestamp BIGINTvisibility STRINGlikeCount INT
Stores posts created by users with metadata.
🔌
CreateUser
Request
{
  "username": "string"
}
Response
{
  "userId": "string",
  "status": "success/failure"
}
Creates a new user profile.
🔌
FollowUser
Request
{
  "followerId": "string",
  "followeeId": "string"
}
Response
{
  "status": "success/failure"
}
Allows a user to follow another user.
🔌
GetFeed
Request
{
  "userId": "string"
}
Response
{
  "posts": "List<Post>"
}
Retrieves personalized feed for a user.

Practice

(1/5)
1. In the Hotel Management System, the RoomManager class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here and why is this the correct choice?
easy
A. Prototype pattern, to clone RoomManager instances efficiently.
B. Factory pattern, because it controls object creation centrally.
C. Builder pattern, to construct complex RoomManager objects step-by-step.
D. Singleton pattern, to ensure only one instance manages room allocation.

Solution

  1. Step 1: Identify the pattern from constructor and method

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single shared instance, which matches the Singleton pattern.
  2. Step 2: Why Singleton fits RoomManager

    RoomManager manages shared state like room availability; having multiple instances risks inconsistent state. Singleton ensures centralized control.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Private constructor + synchronized static getInstance() -> Singleton [check]
Hint: Private constructor + static getInstance() -> Singleton [check]
Common Mistakes:
2. In designing a Vehicle abstraction for a parking system, should Vehicle be an abstract class or an interface if it needs to hold state like licensePlate and provide default behavior for getSize()? Why?
easy
A. Abstract class, because it can hold shared state and provide default method implementations.
B. Interface, because it allows multiple inheritance and enforces method contracts without state.
C. Interface, because Java 8+ interfaces can have default methods and fields for state.
D. Abstract class, because it forces all subclasses to implement all methods explicitly.

Solution

  1. Step 1: Analyze state and behavior requirements

    Vehicle needs to hold state (licensePlate) and provide default behavior (getSize), which interfaces cannot hold as fields.
  2. Step 2: Choose abstraction supporting state and default behavior

    Abstract classes support instance variables and method implementations; interfaces cannot hold instance state.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Abstract class supports state and default behavior -> correct choice [check]
Hint: State needs abstract class; interfaces can't hold instance fields [check]
Common Mistakes:
3. A class provides a createIterator() method that returns an object allowing traversal over its elements without exposing its internal data structure. Which design pattern is being applied and why is this the correct choice?
easy
A. Factory Method pattern, because it encapsulates object creation logic.
B. Decorator pattern, because it adds traversal behavior dynamically.
C. Iterator pattern, because it separates traversal logic from the collection's internal structure.
D. Composite pattern, because it treats individual and composite objects uniformly.

Solution

  1. Step 1: Identify the role of createIterator()

    This method returns an object that allows clients to traverse elements without exposing the collection's internal representation, which is the core intent of the Iterator pattern.
  2. Step 2: Eliminate other patterns

    Factory Method focuses on object creation, Decorator adds responsibilities dynamically, and Composite manages tree structures. None focus on traversal abstraction.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Iterator separates traversal from collection internals [check]
Hint: Iterator hides structure, exposes traversal [check]
Common Mistakes:
4. In a multi-threaded Java Observer implementation, if notifyObservers() is not synchronized, which exact sequence of events can cause observers to receive inconsistent or duplicate updates?
medium
A. Thread 1 checks observer list size -> 3, context switch; Thread 2 removes an observer -> size 2; Thread 1 continues notifying 3 observers, causing duplicate notifications.
B. Thread 1 calls notifyObservers(), Thread 2 waits until Thread 1 finishes, then calls notifyObservers().
C. Thread 1 and Thread 2 both add observers simultaneously, causing a ConcurrentModificationException during notification.
D. Thread 1 updates subject state, Thread 2 reads old state before notification, causing stale data delivery.

Solution

  1. Step 1: Identify race condition in notifyObservers()

    Without synchronization, Thread 1 reads observer list size as 3, then context switches.
  2. Step 2: Thread 2 modifies observer list by removing one observer, reducing size to 2.

    Thread 1 resumes and tries to notify 3 observers, causing out-of-date or duplicate notifications.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Unsynchronized notifyObservers() -> stale observer list read -> inconsistent notifications [check]
Hint: Unsynchronized notify reads stale observer list -> duplicate notifications [check]
Common Mistakes:
5. To support ElectricCar bidders requiring ChargingSpot reservations in the auction system, what is the minimum change to the current Java design to maintain extensibility without modifying existing classes?
hard
A. Modify Vehicle base class to include charging logic and add ChargingSpot as a subclass of Spot.
B. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally.
C. Create a new ElectricCarChargingManager class that extends AuctionManager and handles charging spots internally.
D. Add charging logic directly inside existing Bid and Spot classes to handle electric cars.

Solution

  1. Step 1: Identify extensibility without modification

    Adding new enum values and subclasses extends functionality without changing existing class code.
  2. Step 2: Update SpotCompatibility map externally to maintain compatibility rules without modifying existing classes.

  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Extend enums + subclass + external map update -> minimal change [check]
Hint: Extend enums + subclass + external map update -> minimal change [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard