← Back to all projects

LEARN JAVA OOP DESIGN PATTERNS

Learn Java, OOP, and Design Patterns: From First Principles to Enterprise-Ready Code

Goal: Achieve a deep and practical understanding of Java and the Object-Oriented paradigm. Go beyond syntax to master the art of building robust, maintainable, and scalable software using industry-standard Design Patterns.


Why Learn Java, OOP, and Design Patterns?

Java is a cornerstone of the enterprise world, powering everything from massive web applications and Android apps to data processing pipelines. Its strength lies not just in the language itself, but in the Object-Oriented Programming (OOP) principles and Design Patterns that enable developers to manage complexity in large systems.

After completing these projects, you will:

  • Write clean, idiomatic, and modern Java.
  • Think in terms of objects, classes, and the four pillars of OOP: Encapsulation, Abstraction, Inheritance, and Polymorphism.
  • Recognize common software problems and apply the correct Design Pattern to solve them elegantly.
  • Structure your applications for testability, flexibility, and long-term maintenance.
  • Be equipped with the foundational skills required for professional Java development.

Core Concept Analysis

1. The Four Pillars of OOP

Object-Oriented Programming is a paradigm for structuring programs around “objects” rather than functions and logic.

┌──────────────────────────┐      ┌──────────────────────────┐
│      ENCAPSULATION       │      │        ABSTRACTION         │
│(Data + Methods in one unit)│      │   (Hide complex details)   │
│                          │      │                          │
│   class Car {            │      │   interface Drivable {   │
│     private int speed;   │      │     void accelerate();    │
│     public void start(){ │      │     void brake();         │
│       // ...             │      │   }                      │
│     }                    │      │                          │
│   }                      │      └──────────────────────────┘
└──────────────────────────┘                      ▲
           │                                      │ Implements
           ▼                                      │
┌──────────────────────────┐      ┌──────────────────────────┐
│        INHERITANCE       │      │       POLYMORPHISM         │
│   (Derive new classes)   │      │ (One interface, many forms)│
│                          │      │                          │
│ class ElectricCar        │      │ Drivable myCar = new Car();│
│         extends Car {    │      │ Drivable yourCar =        │
│    // Inherits start()   │      │     new ElectricCar();   │
│    // Adds batteryLevel  │      │                          │
│  }                       │      │ // Both can accelerate() │
└──────────────────────────┘      └──────────────────────────┘

2. Design Patterns: Reusable Blueprints

Design Patterns are generalized, reusable solutions to commonly occurring problems within a given context. They are not code you copy, but rather templates for how to structure your code.

Example: The Strategy Pattern

Problem: You need to perform an action, but there are multiple ways (algorithms) to do it, and you want to be able to switch between them at runtime.

                       ┌────────────────┐
                       │    Context     │
                       │ (e.g., Sorter) │
                       └───────┬────────┘
                               │ has-a
                               ▼
                        ┌────────────────┐
                        │   <<interface>>│
                        │    Strategy    │
                        │(e.g., SortStrategy)│
                        └───────┬────────┘
                                ▲
              ┌─────────────────┴─────────────────┐
              │                 │                 │
      ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
      │  Concrete A   │ │  Concrete B   │ │  Concrete C   │
      │(e.g., BubbleSort)│(e.g., QuickSort)│(e.g., MergeSort)│
      └───────────────┘ └───────────────┘ └───────────────┘

Why it matters: Instead of a giant if/else block in your Sorter class, you simply give it a different SortStrategy object. This makes your code cleaner, more flexible, and easier to extend with new sorting algorithms.


Project List

These projects are designed to be completed in order, as each one introduces new OOP concepts and Design Patterns that build upon the previous ones.


Project 1: Personal Library Management System

  • File: LEARN_JAVA_OOP_DESIGN_PATTERNS.md
  • Main Programming Language: Java
  • Alternative Programming Languages: C#, Python
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: Core OOP / Java Collections
  • Software or Tool: Maven or Gradle, any IDE
  • Main Book: “Effective Java” by Joshua Bloch

What you’ll build: A console application to manage a personal book collection. You’ll be able to add books with details (title, author, ISBN), remove them, and list all books in the library.

Why it teaches OOP: This is the “Hello, World!” of object-oriented design. It forces you to move from primitive variables to creating your own types (Book, Library). You’ll immediately grapple with Encapsulation by bundling data and behavior together.

Core challenges you’ll face:

  • Defining a Book class → maps to modeling real-world objects with fields and methods
  • Implementing a Library class to hold books → maps to creating a class that manages a collection of other objects
  • Hiding internal data structures → maps to practicing Encapsulation with private fields and public methods
  • Handling user input from the console → maps to basic Java I/O with Scanner

Key Concepts:

  • Classes and Objects: “Head First Java” Chapter 2 & 3 - Sierra & Bates
  • Encapsulation: “Effective Java” Item 15: Minimize the accessibility of classes and members - Bloch
  • Java Collections Framework (ArrayList): “Head First Java” Chapter 16

Difficulty: Beginner Time estimate: Weekend Prerequisites: Basic knowledge of Java syntax (variables, loops, methods).

Real world outcome: A running console application where you can interactively manage your book collection.

(Console Output)

Welcome to your Personal Library!
1. Add a Book
2. Remove a Book
3. List All Books
4. Exit
> 1
Enter Title: The Pragmatic Programmer
Enter Author: Andy Hunt
Book added successfully!
> 3
[1] The Pragmatic Programmer by Andy Hunt (ISBN: ...)

Implementation Hints:

  • Start by designing the Book class. What information does a book have? (title, author, ISBN). Make these fields private.
  • How do you create a Book object? You’ll need a constructor.
  • How do you access the book’s title after it’s created? You’ll need a public “getter” method, e.g., getTitle().
  • Your Library class will likely have a private List<Book> books;. How do you add a book to this list? The Library class should have an addBook(Book book) method. It should not expose the raw List to the outside world.

Learning milestones:

  1. Create a Book class with a proper toString() method → You can model data.
  2. Implement the Library class that manages a List<Book> → You can model composition (a class that “has” other objects).
  3. Build a working console menu → You can create a simple but complete application.
  4. Refactor to ensure all fields are private → You understand and can apply encapsulation.

Project 2: A Text-Based Adventure Game

  • File: LEARN_JAVA_OOP_DESIGN_PATTERNS.md
  • Main Programming Language: Java
  • Alternative Programming Languages: C++, Python
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Inheritance & Polymorphism
  • Software or Tool: Maven or Gradle
  • Main Book: “Head First Design Patterns” by Freeman & Robson

What you’ll build: A simple “Zork”-like adventure game where the player navigates a world made of interconnected rooms, can pick up items, and interact with simple characters.

Why it teaches OOP: This project is a masterclass in Inheritance and Polymorphism. You’ll realize that a Player, a Monster, and an Item all share common properties (like a name and description), leading you naturally to create a base class.

Core challenges you’ll face:

  • Designing a class hierarchy for game objects → maps to using inheritance effectively with abstract classes or interfaces
  • Managing game state (player location, inventory) → maps to object composition and relationships
  • Implementing a game loop and parsing user commands → maps to building the core engine of an interactive application
  • Leveraging polymorphism to handle different objects uniformly → maps to writing cleaner, more scalable code

Key Concepts:

  • Inheritance & Abstract Classes: “Head First Java” Chapter 7 & 8
  • Polymorphism: “Effective Java” Item 52: Refer to objects by their interfaces
  • HashMap for room connections: Java Collections Framework documentation

Difficulty: Intermediate Time estimate: 1-2 weeks Prerequisites: Project 1, understanding of classes and objects.

Real world outcome: An interactive console game. You can type commands like “go north”, “take key”, “look”, and the game world will respond.

(Console Output)

You are in a dusty library. There are exits to the north and east.
A rusty key is on the table.
> take key
You picked up the rusty key.
> go north
You are in a dark hallway. There is a locked door to the north.
> unlock door with key
The door clicks open!

Implementation Hints:

  • Create an abstract base class called GameObject with properties like name and description.
  • Create subclasses like Room, Player, Item, Monster that extend GameObject.
  • A Room object might contain a List<Item> and a HashMap<String, Room> to represent its exits (e.g., exits.put("north", hallway);).
  • The real power comes from polymorphism. A Room can have a List<GameObject> inside it, and you can iterate through this list and call a common method like getDescription() on each object, regardless of whether it’s an Item or a Monster.
  • Your game loop will read a command, parse it into an action and a target (e.g., “take”, “key”), and then update the game state accordingly.

Learning milestones:

  1. Create the GameObject hierarchy → You understand inheritance.
  2. Implement rooms with items and interconnected exits → You understand object composition.
  3. Write a game loop that processes different GameObjects uniformly → You understand polymorphism.
  4. Implement a simple command parser → You can build a fully interactive system.

Project 3: A Pizza Delivery Order System

  • File: LEARN_JAVA_OOP_DESIGN_PATTERNS.md
  • Main Programming Language: Java
  • Alternative Programming Languages: C#, Kotlin
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Creational Design Patterns
  • Software or Tool: Maven or Gradle
  • Main Book: “Design Patterns: Elements of Reusable Object-Oriented Software” by Gamma, Helm, Johnson, Vlissides (GoF)

What you’ll build: A system for creating custom pizza orders. This will involve handling different pizza types, sizes, crusts, and a variable number of toppings.

Why it teaches OOP & Design Patterns: This project is perfect for learning Creational Patterns. Constructing a Pizza object is complex—it has many optional parts. This is a classic problem that the Builder Pattern solves elegantly. The Factory Pattern also fits naturally for creating different styles of pizzas.

Core challenges you’ll face:

  • Handling a complex object with many optional parameters → maps to the problem that the Builder pattern solves
  • Avoiding a “telescoping constructor” (Pizza(size, crust, cheese, pepperoni, ...) → maps to writing clean and readable object creation code
  • Creating different “families” of related objects (e.g., NY-style vs. Chicago-style) → maps to the problem that the Factory pattern solves
  • Decoupling the client code from the concrete classes of the pizzas it creates → maps to writing more flexible and extensible systems

Key Concepts:

  • Builder Pattern: “Effective Java” Item 2: Consider a builder when faced with many constructor parameters.
  • Factory Method Pattern: “Head First Design Patterns” Chapter 4.
  • Static Nested Classes: The Builder pattern is often implemented as a static nested class.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 2, solid understanding of OOP principles.

Real world outcome: A program that allows you to define and price pizzas using a clean, fluent API.

// Not a console app, but the API you build is the outcome.
public static void main(String[] args) {
    // Using the Builder Pattern
    Pizza veggieDelight = new Pizza.Builder(Size.LARGE)
        .crust(Crust.THIN)
        .addTopping(Topping.MUSHROOM)
        .addTopping(Topping.ONION)
        .addTopping(Topping.BELL_PEPPER)
        .build();

    System.out.println("Created: " + veggieDelight);
    System.out.println("Price: $" + veggieDelight.getPrice());

    // Using the Factory Pattern
    PizzaShop nyShop = new NYPizzaShop();
    Pizza nyCheesePizza = nyShop.orderPizza("cheese");
    System.out.println("Ordered: " + nyCheesePizza);
}

Implementation Hints:

  • For the Builder: Create a public static class Builder inside your Pizza class. The Builder will have methods like crust(Crust c) that return this (the builder instance itself) to allow for chaining. It will have a final build() method that creates the Pizza object.
  • For the Factory: Create an abstract PizzaShop class with an abstract Pizza createPizza(String type) method. Then create concrete subclasses like NYPizzaShop and ChicagoPizzaShop that implement createPizza to return their specific regional styles. Your orderPizza method in the base class will call createPizza.

Learning milestones:

  1. Implement a Pizza class with a telescoping constructor and see why it’s bad → Understand the problem.
  2. Refactor the Pizza class to use the Builder pattern → Master the Builder pattern for complex object creation.
  3. Implement the PizzaShop factory method → Master the Factory pattern for delegating instantiation to subclasses.
  4. Combine the patterns so the Factory uses the Builder to construct the pizzas.

Project 4: A Smart Home Control System

  • File: LEARN_JAVA_OOP_DESIGN_PATTERNS.md
  • Main Programming Language: Java
  • Alternative Programming Languages: C#, Python
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Behavioral & Structural Design Patterns
  • Software or Tool: Maven or Gradle
  • Main Book: “Head First Design Patterns” by Freeman & Robson

What you’ll build: A console simulation of a smart home remote control. You’ll have devices like lights, thermostats, and speakers. The remote will have “slots” for commands, and you’ll be able to program these slots to perform actions like “turn on living room light” or “set thermostat to 72 degrees.”

Why it teaches OOP & Design Patterns: This project is a fantastic playground for Behavioral and Structural Patterns.

  • Command Pattern: You can encapsulate each action (e.g., “light on,” “thermostat up”) into a command object. This decouples the remote control (the “invoker”) from the devices (the “receivers”). It also makes implementing an “undo” feature trivial!
  • Adapter Pattern: What if you buy a new smart speaker with a completely different API? You can write an Adapter that makes the new speaker’s API compatible with your existing SmartDevice interface.
  • Facade Pattern: You can create a “movie night” Facade that simplifies a complex set of actions (dim lights, close blinds, turn on TV) into a single startMovieNight() method.

Key Concepts:

  • Command Pattern: “Head First Design Patterns” Chapter 6.
  • Adapter Pattern: “Head First Design Patterns” Chapter 7.
  • Facade Pattern: “Head First Design Patterns” Chapter 7.
  • Interfaces: Using interfaces (SmartDevice) to define a common contract for all devices.

Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: Project 3, strong grasp of interfaces and polymorphism.

Real world outcome: A flexible and extensible smart home simulator. You can assign commands to slots, execute them, and see the state of your devices change.

(Console Output)

--- Smart Remote ---
[Slot 1] Turn Living Room Light On
[Slot 2] Turn Kitchen Light Off
[Slot 3] Set Thermostat to 72
[Slot 4] Movie Night Routine
[UNDO]
Enter slot number to execute: 1
Executing: Turn Living Room Light On
> Living Room Light is now ON.

Enter slot number to execute: UNDO
Undoing last command...
> Living Room Light is now OFF.

Implementation Hints:

  • Define a Command interface with a single execute() method (and maybe an undo() method).
  • Create concrete command classes like LightOnCommand, LightOffCommand, etc. These classes will hold a reference to the device they operate on (e.g., a Light object).
  • The RemoteControl class will have an array or list of Command objects. The onButtonWasPushed(int slot) method will simply call commands[slot].execute().
  • To implement undo, the remote can store the last executed command in a lastCommand field. The undo action simply calls lastCommand.undo().

Learning milestones:

  1. Define device interfaces and concrete device classes → Establish the “receivers”.
  2. Implement the Command pattern for simple on/off actions → Decouple invoker from receiver.
  3. Implement an “undo” function using the Command pattern → See the power of encapsulating actions.
  4. Implement an Adapter for a new, incompatible device → Master the Adapter pattern for integrating legacy or third-party code.
  5. Implement a Facade for a “routine” → Learn to simplify complex subsystems.

Project Comparison Table

Project Difficulty Time Key Concepts Taught Fun Factor
1. Library Beginner Weekend Encapsulation, Collections 📚📚
2. Adventure Game Intermediate 1-2 weeks Inheritance, Polymorphism ⚔️⚔️⚔️⚔️
3. Pizza Shop Advanced 1-2 weeks Builder, Factory Patterns 🍕🍕🍕🍕🍕
4. Smart Home Advanced 2-3 weeks Command, Adapter, Facade 💡💡💡💡

Recommendation

It is highly recommended to follow the projects in order.

  • Start with Project 1: Personal Library Management System. It’s essential to master the fundamentals of classes, objects, and encapsulation before moving on. This project ensures you have a solid footing.
  • Move to Project 2: Text-Based Adventure Game to truly internalize inheritance and polymorphism, which are the heart of OOP.
  • Only once you are comfortable with those OOP pillars should you proceed to Projects 3 and 4, which introduce formal Design Patterns. Trying to learn patterns without a solid OOP foundation can be confusing and lead to misapplication.

Final Overall Project: A Hotel Reservation System

  • File: LEARN_JAVA_OOP_DESIGN_PATTERNS.md
  • Main Programming Language: Java
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 5: Master
  • Knowledge Area: Integrating Multiple Design Patterns
  • Software or Tool: JavaFX (for GUI), Maven/Gradle, maybe H2/SQLite (for persistence)
  • Main Book: “Design Patterns: Elements of Reusable Object-Oriented Software” (GoF)

What you’ll build: A complete hotel reservation management application, either as a rich console app or a simple GUI app using JavaFX. It will manage rooms, guests, and bookings, and handle pricing.

Why it’s the capstone project: This project is complex enough to require the thoughtful application of multiple design patterns working together. It simulates a real-world business application and forces you to think about the entire system architecture.

Core concepts you’ll integrate:

  • Factory Pattern: A RoomFactory to create different types of rooms (StandardRoom, DeluxeRoom, Suite).
  • Builder Pattern: A BookingBuilder for constructing complex Booking objects (which include dates, guest info, special requests, meal plans, etc.).
  • Observer Pattern: When a guest checks out, a Booking object can notify the HousekeepingService (an observer) that the room needs cleaning.
  • Strategy Pattern: Implement different pricing models (WeekdayPricingStrategy, WeekendPricingStrategy, HolidayPricingStrategy) that can be applied to a room.
  • Singleton Pattern: The core Hotel or ReservationSystem class could be a Singleton to ensure there’s a single source of truth.
  • Facade Pattern: Create a BookingFacade to provide a simple API (bookRoom, cancelBooking) for the UI to interact with, hiding the complexity of the underlying reservation, billing, and notification subsystems.

This final project will be a testament to your mastery of Java, OOP, and Design Patterns, resulting in a significant portfolio piece.


Summary of Projects

Project Main Language
1. Personal Library Management System Java
2. A Text-Based Adventure Game Java
3. A Pizza Delivery Order System Java
4. A Smart Home Control System Java
Final Project: A Hotel Reservation System Java