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/com/iluwatar/immutable/ImmutableObject.java b/immutable/src/main/java/com/iluwatar/immutable/ImmutableObject.java new file mode 100644 index 000000000000..824f41cb22b7 --- /dev/null +++ b/immutable/src/main/java/com/iluwatar/immutable/ImmutableObject.java @@ -0,0 +1,50 @@ +package com.iluwatar.immutable; +import java.util.Objects; + +/** + * 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 = Objects.requireNonNull(name, "name cannot be null"); + this.age = age; + this.email = Objects.requireNonNull(email, "email cannot be null"); + } + + 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 + '\'' + + '}'; + } + + @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 new file mode 100644 index 000000000000..01b7306f48ed --- /dev/null +++ b/immutable/src/test/java/com/iluwatar/immutable/ImmutableObjectTest.java @@ -0,0 +1,52 @@ +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); + } + + @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