Bird
Raised Fist0

Design LinkedIn in OOP - Profile, Connection, Feed, Job, Recommendation

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
RecommendationEngine Singleton

RecommendationEngine is a Singleton with a volatile instance field and synchronized getInstance method.

🎯 Tests whether candidate knows volatile ensures safe publication of the singleton instance and synchronized prevents multiple instantiations in concurrent threads.
public class RecommendationEngine {
    private static volatile RecommendationEngine instance;
    private RecommendationEngine() {}
    public static synchronized RecommendationEngine getInstance() {
        if (instance == null) {
            instance = new RecommendationEngine();
        }
        return instance;
    }
    public List<JobPosting> recommend(UserProfile user) {
        // recommendation logic
    }
}
UserProfile composition with RecommendationEngine

UserProfile composes RecommendationEngine by calling its singleton instance but holds connections and feedPosts as collections.

🎯 Tests understanding of composition vs association: RecommendationEngine is singleton (global), connections/feedPosts are owned by UserProfile (composition implied by lifecycle).
public class UserProfile {
    private String id;
    private String name;
    private List<Connection> connections = new ArrayList<>();
    private List<FeedPost> feedPosts = new ArrayList<>();
    public synchronized void addConnection(Connection c) {
        connections.add(c);
    }
    public void addFeedPost(FeedPost post) {
        feedPosts.add(post);
    }
    public List<JobPosting> getRecommendations() {
        return RecommendationEngine.getInstance().recommend(this);
    }
}
Connection association with UserProfile

Connection holds references to two UserProfiles but does not own them (association).

🎯 Tests whether candidate distinguishes association (no lifecycle ownership) from composition and understands UserProfiles exist independently of connections.
public class Connection {
    private UserProfile user1;
    private UserProfile user2;
    private Date connectedOn;
    public void connect() {
        // logic to establish connection
    }
}
FeedPost association with UserProfile

FeedPost references its author UserProfile but does not own it (association).

🎯 Tests understanding that FeedPost lifecycle is independent but linked to UserProfile by association, not composition.
public class FeedPost {
    private String content;
    private UserProfile author;
    private Date timestamp;
    public void publish() {
        // publishing logic
    }
}
📐
Class Diagram
Class Diagram
       +----------------+
       | <<Singleton>>  |
       |RecommendationEng|
       |----------------|
       | - instance:    |
       |   volatile Rec |
       |----------------|
       | + getInstance():|
       |   RecommendationEng [sync]|
       | + recommend(UserProfile):|
       |   List<JobPosting>       |
       +----------------+
               │
               │ composition
               ▼
       +----------------+
       | UserProfile    |
       |----------------|
       | - id: String   |
       | - name: String |
       | - connections: |
       |   List<Connection>|
       | - feedPosts:   |
       |   List<FeedPost>|
       |----------------|
       | + addConnection(Connection):|
       |   void [sync]             |
       | + addFeedPost(FeedPost): |
       |   void                   |
       +----------------+
               │
               │ association
               ▼
       +----------------+
       | Connection     |
       |----------------|
       | - user1: UserProfile|
       | - user2: UserProfile|
       | - connectedOn: Date|
       |----------------|
       | + connect(): void |
       +----------------+
               │
               │ association
               ▼
       +----------------+
       | FeedPost       |
       |----------------|
       | - content: String|
       | - author: UserProfile|
       | - timestamp: Date|
       |----------------|
       | + publish(): void|
       +----------------+

This class diagram illustrates key Java-specific design decisions for LinkedIn's core entities. RecommendationEngine is implemented as a thread-safe Singleton using a volatile instance and synchronized getInstance method to ensure safe publication and single instantiation in concurrent environments. UserProfile composes collections of Connection and FeedPost objects, showing lifecycle ownership, while associating with the singleton RecommendationEngine. Connections and FeedPosts hold references to UserProfiles via association, reflecting independent lifecycles. Synchronized methods in UserProfile ensure thread-safe mutation of connections. This design enforces SOLID principles by separating concerns and enabling extensibility without modifying existing classes.

Primary Focus

✓ Composition vs Association lifecycle + Abstract class state vs interface + Singleton volatile + Synchronized methods

Practice

(1/5)
1. In the Restaurant Management System, the OrderManager class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here and why is it the correct choice?
easy
A. Factory pattern, because it controls object creation centrally.
B. Builder pattern, to incrementally construct complex orders.
C. Singleton pattern, to ensure only one instance manages all orders globally.
D. Prototype pattern, to clone existing orders efficiently.

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 OrderManager

    OrderManager must coordinate all orders centrally to avoid conflicting states; multiple instances would cause inconsistent order tracking.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Private constructor + synchronized static getInstance() -> Singleton [check]
Hint: Private constructor + static getInstance() -> Singleton [check]
Common Mistakes:
2. In designing the Player abstraction for the Tic-Tac-Toe game, should Player be an abstract class or an interface, and why?
easy
A. Abstract class, because Java interfaces cannot have default methods for shared logic.
B. Interface, because players only define behavior like making moves, allowing multiple inheritance of behavior.
C. Abstract class, because players share common state like name and score that should be inherited.
D. Interface, because it allows storing player state directly in the interface.

Solution

  1. Step 1: Analyze state and behavior requirements

    Players have common state (e.g., name, symbol, score) and some shared behavior (e.g., basic validation). Abstract classes allow state fields and shared method implementations.
  2. Step 2: Why abstract class is better than interface here

    Interfaces define behavior contracts but cannot hold instance state. Although Java 8+ interfaces support default methods, they cannot hold mutable state. Thus, abstract class suits better for shared state and behavior.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Shared state + behavior -> abstract class, not interface [check]
Hint: State needs abstract class; behavior-only fits interface [check]
Common Mistakes:
3. You want to add a WeekendFeeStrategy to calculate parking fees differently on weekends. Given the current design uses a FeeStrategy interface and ParkingLot depends on it, what is the minimum change to comply with SOLID principles?
medium
A. Add a boolean flag isWeekend to FeeStrategy and update all implementations.
B. Create a new WeekendFeeStrategy implementing FeeStrategy and inject it without changing ParkingLot.
C. Modify ParkingLot to detect weekends and apply extra fees internally.
D. Combine all fee calculations into a single ComplexFeeStrategy class.

Solution

  1. Step 1: Identify SOLID principle involved

    The Open-Closed Principle (OCP) requires that ParkingLot should be open for extension but closed for modification.
  2. Step 2: Evaluate options against OCP

    Modify ParkingLot to detect weekends and apply extra fees internally. modifies ParkingLot, violating OCP. Create a new WeekendFeeStrategy implementing FeeStrategy and inject it without changing ParkingLot. adds a new strategy class and injects it, adhering to OCP. Add a boolean flag isWeekend to FeeStrategy and update all implementations. adds a flag to the interface, forcing all implementations to change, violating OCP. Combine all fee calculations into a single ComplexFeeStrategy class. merges logic, increasing complexity and violating Single Responsibility Principle.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class extends behavior without modifying existing code [check]
Hint: OCP: add new strategy class, don't modify existing code [check]
Common Mistakes:
4. The auction system currently calculates fees with a fixed strategy. To add a WeekendFeeStrategy without modifying existing classes, which SOLID principle is being applied and what is the minimum required change?
medium
A. Open/Closed Principle: create a new WeekendFeeStrategy class implementing FeeStrategy; inject it without changing existing code.
B. Liskov Substitution Principle: subclass Auction to WeekendAuction overriding fee calculation.
C. Single Responsibility Principle: modify Auction class to handle weekend fees directly.
D. Dependency Inversion Principle: hardcode weekend fee logic inside FeeStrategy implementation.

Solution

  1. Step 1: Identify SOLID principle

    Open/Closed Principle (OCP) states software entities should be open for extension but closed for modification.
  2. Step 2: Apply OCP by adding WeekendFeeStrategy implementing FeeStrategy interface without modifying existing classes.

  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class + injection -> OCP compliance [check]
Hint: Add new strategy class, no existing code change -> OCP [check]
Common Mistakes:
5. In a multi-threaded environment, if the addProductToCart() method is not synchronized, which exact sequence of events can cause the cart to contain duplicate entries for the same product?
medium
A. Thread 1 checks if product exists -> false, context switch; Thread 2 checks -> false; both add product concurrently.
B. Thread 1 adds product, Thread 2 removes product simultaneously causing inconsistency.
C. Thread 1 updates quantity, Thread 2 reads stale quantity due to lack of volatile keyword.
D. Thread 1 locks cart, Thread 2 waits but eventually overwrites product quantity.

Solution

  1. Step 1: Identify check-then-act race condition

    Both threads check if product exists and see false before either adds it, due to lack of synchronization.
  2. Step 2: Both threads add product concurrently causing duplicates

    Because the add operation is not atomic, both add the product, resulting in duplicates.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Check-then-act gap without synchronization -> duplicate entries [check]
Hint: Check-then-act gap -> duplicate add without sync [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