From 0fd6085a383bb9ffcadad340c3ed596cdad18737 Mon Sep 17 00:00:00 2001 From: prashantpiyush1111 Date: Wed, 27 May 2026 12:17:11 +0530 Subject: [PATCH 1/4] feat: add Immutable Object design pattern (#3448) --- immutable/README.md | 18 +++++++++++ immutable/pom.xml | 20 ++++++++++++ immutable/src/main/java/ImmutableObject.java | 34 ++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 immutable/README.md create mode 100644 immutable/pom.xml create mode 100644 immutable/src/main/java/ImmutableObject.java diff --git a/immutable/README.md b/immutable/README.md new file mode 100644 index 000000000000..848dda01cb4c --- /dev/null +++ b/immutable/README.md @@ -0,0 +1,18 @@ +# Immutable Object Pattern + +## Intent +Ensure that an object's state cannot be modified +after it is created. + +## Explanation +An immutable object is one whose state cannot be +changed once created. All fields are final and set +only in the constructor. + +## When to use +- When shared objects must not be changed +- For thread-safe programming +- When you need predictable behavior + +## Example +HeroStats in a game — once created, stats remain fixed. \ No newline at end of file diff --git a/immutable/pom.xml b/immutable/pom.xml new file mode 100644 index 000000000000..7699e8dc1bea --- /dev/null +++ b/immutable/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + immutable + + + org.junit.jupiter + junit-jupiter-engine + test + + + \ No newline at end of file diff --git a/immutable/src/main/java/ImmutableObject.java b/immutable/src/main/java/ImmutableObject.java new file mode 100644 index 000000000000..307154602b4e --- /dev/null +++ b/immutable/src/main/java/ImmutableObject.java @@ -0,0 +1,34 @@ +package com.iluwatar.immutable; + +/** + * Immutable Object pattern. + * Once created, the object state cannot be changed. + */ +public final class ImmutableObject { + + private final String name; + private final int age; + private final String email; + + public ImmutableObject( + final String name, + final int age, + final String email) { + this.name = name; + this.age = age; + this.email = email; + } + + public String getName() { return name; } + public int getAge() { return age; } + public String getEmail() { return email; } + + @Override + public String toString() { + return "ImmutableObject{" + + "name='" + name + '\'' + + ", age=" + age + + ", email='" + email + '\'' + + '}'; + } +} \ No newline at end of file From 7cdf02b0611491c08118f0ace7082b687a64f550 Mon Sep 17 00:00:00 2001 From: prashantpiyush1111 Date: Wed, 27 May 2026 12:31:54 +0530 Subject: [PATCH 2/4] fix: move ImmutableObject to correct package path --- .../main/java/{ => com/iluwatar/immutable}/ImmutableObject.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename immutable/src/main/java/{ => com/iluwatar/immutable}/ImmutableObject.java (100%) diff --git a/immutable/src/main/java/ImmutableObject.java b/immutable/src/main/java/com/iluwatar/immutable/ImmutableObject.java similarity index 100% rename from immutable/src/main/java/ImmutableObject.java rename to immutable/src/main/java/com/iluwatar/immutable/ImmutableObject.java From 1c415047f4068f73170aa7ca4e40a5f6a65ba889 Mon Sep 17 00:00:00 2001 From: prashantpiyush1111 Date: Wed, 27 May 2026 13:30:31 +0530 Subject: [PATCH 3/4] test: add ImmutableObjectTest for coverage --- .../immutable/ImmutableObjectTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java diff --git a/immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java b/immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java new file mode 100644 index 000000000000..6df58046965f --- /dev/null +++ b/immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java @@ -0,0 +1,35 @@ +package com.iluwatar.immutable; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class ImmutableObjectTest { + + @Test + void testObjectCreation() { + ImmutableObject obj = + new ImmutableObject("Prashant", 22, "p@gmail.com"); + + assertEquals("Prashant", obj.getName()); + assertEquals(22, obj.getAge()); + assertEquals("p@gmail.com", obj.getEmail()); + } + + @Test + void testToString() { + ImmutableObject obj = + new ImmutableObject("Prashant", 22, "p@gmail.com"); + + assertTrue(obj.toString().contains("Prashant")); + } + + @Test + void testImmutability() { + ImmutableObject obj1 = + new ImmutableObject("A", 1, "a@gmail.com"); + ImmutableObject obj2 = + new ImmutableObject("A", 1, "a@gmail.com"); + + assertNotSame(obj1, obj2); + } +} \ No newline at end of file From 26287aa6266da7ff2a00e9b219c38946455ec96e Mon Sep 17 00:00:00 2001 From: prashantpiyush1111 Date: Wed, 27 May 2026 13:37:09 +0530 Subject: [PATCH 4/4] refactor: add equals, hashCode, null safety and tests --- .../iluwatar/immutable/ImmutableObject.java | 20 +++++++++++++++++-- .../immutable/ImmutableObjectTest.java | 17 ++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/immutable/src/main/java/com/iluwatar/immutable/ImmutableObject.java b/immutable/src/main/java/com/iluwatar/immutable/ImmutableObject.java index 307154602b4e..824f41cb22b7 100644 --- a/immutable/src/main/java/com/iluwatar/immutable/ImmutableObject.java +++ b/immutable/src/main/java/com/iluwatar/immutable/ImmutableObject.java @@ -1,4 +1,5 @@ package com.iluwatar.immutable; +import java.util.Objects; /** * Immutable Object pattern. @@ -14,9 +15,9 @@ public ImmutableObject( final String name, final int age, final String email) { - this.name = name; + this.name = Objects.requireNonNull(name, "name cannot be null"); this.age = age; - this.email = email; + this.email = Objects.requireNonNull(email, "email cannot be null"); } public String getName() { return name; } @@ -31,4 +32,19 @@ public String toString() { + ", email='" + email + '\'' + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ImmutableObject)) return false; + ImmutableObject that = (ImmutableObject) o; + return age == that.age + && Objects.equals(name, that.name) + && Objects.equals(email, that.email); + } + + @Override + public int hashCode() { + return Objects.hash(name, age, email); + } } \ No newline at end of file diff --git a/immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java b/immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java index 6df58046965f..01b7306f48ed 100644 --- a/immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java +++ b/immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java @@ -32,4 +32,21 @@ void testImmutability() { assertNotSame(obj1, obj2); } + + @Test + void testEquality() { + ImmutableObject obj1 = + new ImmutableObject("A", 1, "a@gmail.com"); + ImmutableObject obj2 = + new ImmutableObject("A", 1, "a@gmail.com"); + + assertEquals(obj1, obj2); + } + + @Test + void testNullName() { + assertThrows(NullPointerException.class, () -> { + new ImmutableObject(null, 1, "a@gmail.com"); + }); + } } \ No newline at end of file