Skip to content

arefiva/ProductStore

Repository files navigation

Product Store Inventory Management System

This is a comprehensive Java learning project that demonstrates key concepts through a practical example.

Learning Objectives

This project teaches:

  1. Class Design - Different approaches to designing classes (mutable vs immutable)
  2. Fields, Getters, and Setters - Encapsulation and data hiding
  3. Constructors - Ensuring objects are created in valid states
  4. Loops - Different types of loops and when to use each
  5. Conditionals and Booleans - Control flow and logical operations
  6. Lambda Expressions - Functional programming in Java

Project Structure

src/
├── Main.java                      - Main demonstration program
├── Exercises.java                 - Student exercises (6 levels)
├── ExercisesSolutions.java        - Complete solutions to all exercises
├── FullyMutableProduct.java       - Example 1: All public fields
├── ProductWithGettersSetters.java - Example 2: Private fields with getters/setters
├── ProductWithConstructor.java    - Example 3: Constructor with partial immutability
├── ImmutableProduct.java          - Example 4: Fully immutable class (BEST PRACTICE)
├── ProductFilter.java             - Functional interface for filtering
├── ProductProcessor.java          - Functional interface for processing
└── InventoryManager.java          - Lambda demonstration helper class

How to Run

In IntelliJ IDEA:

  1. Run demonstrations: Right-click on Main.java → Select "Run 'Main.main()'"
  2. Practice exercises: Right-click on Exercises.java → Select "Run 'Exercises.main()'"
  3. Check solutions: Right-click on ExercisesSolutions.java → Select "Run"

Or from command line (if you have JDK installed):

cd src
javac *.java
java Main              # Run demonstrations
java Exercises         # Run exercises
java ExercisesSolutions # Run solutions

Learning Path

  1. Study the examples - Run Main.java and read through the code
  2. Complete the exercises - Open Exercises.java and solve them one by one
  3. Check your work - Compare with ExercisesSolutions.java
  4. Experiment - Modify the code and see what happens!

Key Concepts Demonstrated

1. Class Design Patterns

FullyMutableProduct - Maximum Flexibility, Minimum Safety

FullyMutableProduct product = new FullyMutableProduct();
product.id = 1;           // All fields are public
product.name = "Laptop";  // Can be changed anytime

Problems:

  • Fields can be null (NullPointerException risk)
  • No validation possible
  • Values can change unexpectedly
  • Not thread-safe

ProductWithGettersSetters - Better Encapsulation

ProductWithGettersSetters product = new ProductWithGettersSetters();
product.setId(1);        // Setters can validate input
product.setName("Laptop");

Benefits:

  • Can add validation in setters
  • Can change internal implementation
  • Encapsulation of data

Problems:

  • Still mutable (values can change)
  • Still need null checks

ProductWithConstructor - Partial Immutability

// Must provide id and name at creation
ProductWithConstructor product = new ProductWithConstructor(1, "Laptop");
product.price = 99.99;  // Other fields still public

What a Constructor Does:

  • Ensures required fields are set at object creation
  • Cannot create object without providing required values
  • Some fields can be made immutable (final, no setter)

ImmutableProduct - Best Practice (RECOMMENDED)

// All fields must be provided at creation
ImmutableProduct product = new ImmutableProduct(1, "Laptop", 999.99, 10);
// product.setPrice(100); // Won't compile - no setters!

Benefits:

  • Thread-safe (can share between threads safely)
  • No unexpected changes
  • No null checks needed (guaranteed valid values)
  • Easier to reason about
  • Can be used as Map keys or in Sets

Trade-off:

  • To "change" a value, must create new object

2. Loop Types

For Loop - Use when you need the index

for (int i = 0; i < inventory.length; i++) {
    System.out.println("[" + i + "] " + inventory[i].getName());
}

Use cases:

  • Need to know the position/index
  • Iterate in reverse order
  • Skip elements (iterate by 2s, 3s, etc.)
  • Modify elements in place

Foreach Loop - Use when you just need each element

for (ImmutableProduct product : inventory) {
    System.out.println(product.getName());
}

Use cases:

  • Simpler, cleaner code
  • Don't need the index
  • Just processing each element

While Loop - Use when iterations are unknown

// Example: Stop when budget runs out
double budget = 500.0;
int i = 0;
while (i < inventory.length && budget >= inventory[i].getPrice()) {
    budget -= inventory[i].getPrice();
    i++;
}

Use cases:

  • Early exit (stop as soon as item found - don't check remaining items)
  • Budget/resource limits (unknown how many iterations until limit hit)
  • Multiple exit conditions (cart full OR expensive item found)
  • Accumulated thresholds (process until total value exceeds limit)
  • Key insight: foreach processes ALL items; while stops when condition met!

3. Conditionals and Booleans

boolean isExpensive = product.getPrice() > 100;
boolean isLowStock = product.getQuantity() < 15;
boolean needsReorder = isLowStock && product.getPrice() > 50;

if (isExpensive && isLowStock) {
    System.out.println("ALERT: Expensive item with low stock!");
} else if (isLowStock) {
    System.out.println("Low stock warning");
} else {
    System.out.println("Stock level normal");
}

4. Lambda Expressions

Lambdas allow you to pass behavior as a parameter:

// Filter products over $100
ImmutableProduct[] expensive = manager.filter(product -> product.getPrice() > 100);

// Filter low stock items
ImmutableProduct[] lowStock = manager.filter(product -> product.getQuantity() < 15);

// Process each product
manager.forEach(product -> {
    double discounted = product.getPrice() * 0.9;
    System.out.println(product.getName() + ": $" + discounted);
});

Benefits:

  • Flexible, reusable code
  • Pass behavior as parameter
  • Cleaner than anonymous classes
  • Enables functional programming style

Important Lessons

Why Immutability Matters

With Mutable Objects:

FullyMutableProduct product = new FullyMutableProduct();
product.price = 999.99;

// Later in code...
calculateDiscount(product);  // Might change the price!

// Price might have changed unexpectedly!
System.out.println(product.price); // Could be different now

With Immutable Objects:

ImmutableProduct product = new ImmutableProduct(1, "Laptop", 999.99, 10);

calculateDiscount(product);  // Cannot modify the original

// Price is guaranteed to be the same
System.out.println(product.getPrice()); // Still 999.99

Null Safety

Mutable classes require null checks:

if (product.name != null) {
    String upper = product.name.toUpperCase();
}

Immutable classes guarantee no nulls:

// No null check needed - guaranteed to have value
String upper = product.getName().toUpperCase();

Practice Exercises

The project includes 6 levels of exercises in Exercises.java:

Level 1: Class Design Basics (Easy)

  • Create mutable and immutable products
  • Practice using constructors
  • Understand field initialization

Level 2: Simple Loops (Easy)

  • Print products using foreach
  • Count items matching criteria
  • Basic iteration patterns

Level 3: Loop Variations (Medium)

  • Iterate in reverse order
  • Find min/max values
  • Use for loops vs foreach

Level 4: While Loops (Medium)

  • Shop until budget exceeded
  • Search with early exit
  • Unknown iteration counts

Level 5: Conditionals and Booleans (Hard)

  • Categorize items with if-else
  • Use compound boolean expressions
  • Complex business logic

Level 6: Lambdas (Hard)

  • Filter with lambda expressions
  • Process items functionally
  • Use functional interfaces

Tip: Start with Level 1 and work your way up. Each level builds on previous concepts!

Best Practices

  1. Use immutable classes for data objects (recommended)
  2. Validate input in constructors and setters
  3. Make fields private (encapsulation)
  4. Use final for fields that shouldn't change
  5. Choose the right loop for the job
  6. Use lambdas for flexible, reusable code

Running the Examples

The Main.java program demonstrates all concepts in order:

  1. Class design patterns (4 examples)
  2. Loop types (for, foreach, while)
  3. Conditionals and booleans
  4. Lambda expressions

Each section has detailed comments explaining what's happening and why.


Author: Educational Project for Java Learning
Java Version: Java 21+ (uses modern features)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages