Compare commits
	
		
			1 Commits
		
	
	
		
			master
			...
			valueObjec
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d2fab302ce | 
| @@ -10,19 +10,80 @@ tags: | ||||
| --- | ||||
|  | ||||
| ## Intent | ||||
|  | ||||
| Provide objects which follow value semantics rather than reference semantics. | ||||
| This means value objects' equality are not based on identity. Two value objects are | ||||
| This means value objects' equality is not based on identity. Two value objects are | ||||
| equal when they have the same value, not necessarily being the same object. | ||||
|  | ||||
| ## Explanation | ||||
|  | ||||
| Real-world example | ||||
|  | ||||
| > There is a class for hero statistics in a role-playing game. The statistics contain attributes | ||||
| > such as strength, intelligence, and luck. The statistics of different heroes should be equal | ||||
| > when all the attributes are equal. | ||||
|  | ||||
| In plain words | ||||
|  | ||||
| > Value objects are equal when their attributes have the same value | ||||
|  | ||||
| Wikipedia says | ||||
|  | ||||
| > In computer science, a value object is a small object that represents a simple entity whose  | ||||
| > equality is not based on identity: i.e. two value objects are equal when they have the same  | ||||
| > value, not necessarily being the same object. | ||||
|  | ||||
| **Programmatic Example** | ||||
|  | ||||
| Here is the `HeroStat` class that is the value object. Notice the use of  | ||||
| [Lombok's `@Value`](https://projectlombok.org/features/Value) annotation. | ||||
|  | ||||
| ```java | ||||
| @Value(staticConstructor = "valueOf") | ||||
| class HeroStat { | ||||
|  | ||||
|     int strength; | ||||
|     int intelligence; | ||||
|     int luck; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| The example creates three different `HeroStat`s and compares their equality. | ||||
|  | ||||
| ```java | ||||
| var statA = HeroStat.valueOf(10, 5, 0); | ||||
| var statB = HeroStat.valueOf(10, 5, 0); | ||||
| var statC = HeroStat.valueOf(5, 1, 8); | ||||
|  | ||||
| LOGGER.info(statA.toString()); | ||||
| LOGGER.info(statB.toString()); | ||||
| LOGGER.info(statC.toString()); | ||||
|  | ||||
| LOGGER.info("Is statA and statB equal : {}", statA.equals(statB)); | ||||
| LOGGER.info("Is statA and statC equal : {}", statA.equals(statC)); | ||||
| ``` | ||||
|  | ||||
| Here's the console output. | ||||
|  | ||||
| ``` | ||||
| 20:11:12.199 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=10, intelligence=5, luck=0) | ||||
| 20:11:12.202 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=10, intelligence=5, luck=0) | ||||
| 20:11:12.202 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=5, intelligence=1, luck=8) | ||||
| 20:11:12.202 [main] INFO com.iluwatar.value.object.App - Is statA and statB equal : true | ||||
| 20:11:12.203 [main] INFO com.iluwatar.value.object.App - Is statA and statC equal : false | ||||
| ``` | ||||
|  | ||||
| ## Class diagram | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Applicability | ||||
|  | ||||
| Use the Value Object when | ||||
|  | ||||
| * You need to measure the objects' equality based on the objects' value | ||||
| * The object's equality needs to be based on the object's value | ||||
|  | ||||
| ## Real world examples | ||||
| ## Known uses | ||||
|  | ||||
| * [java.util.Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html) | ||||
| * [java.time.LocalDate](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html) | ||||
| @@ -31,6 +92,7 @@ Use the Value Object when | ||||
| ## Credits | ||||
|  | ||||
| * [Patterns of Enterprise Application Architecture](http://www.martinfowler.com/books/eaa.html) | ||||
| * [ValueObject](https://martinfowler.com/bliki/ValueObject.html) | ||||
| * [VALJOs - Value Java Objects : Stephen Colebourne's blog](http://blog.joda.org/2014/03/valjos-value-java-objects.html) | ||||
| * [Value Object : Wikipedia](https://en.wikipedia.org/wiki/Value_object) | ||||
| * [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94) | ||||
|   | ||||
| @@ -43,7 +43,7 @@ import lombok.extern.slf4j.Slf4j; | ||||
| public class App { | ||||
|  | ||||
|   /** | ||||
|    * This practice creates three HeroStats(Value object) and checks equality between those. | ||||
|    * This example creates three HeroStats (value objects) and checks equality between those. | ||||
|    */ | ||||
|   public static void main(String[] args) { | ||||
|     var statA = HeroStat.valueOf(10, 5, 0); | ||||
| @@ -51,6 +51,8 @@ public class App { | ||||
|     var statC = HeroStat.valueOf(5, 1, 8); | ||||
|  | ||||
|     LOGGER.info(statA.toString()); | ||||
|     LOGGER.info(statB.toString()); | ||||
|     LOGGER.info(statC.toString()); | ||||
|  | ||||
|     LOGGER.info("Is statA and statB equal : {}", statA.equals(statB)); | ||||
|     LOGGER.info("Is statA and statC equal : {}", statA.equals(statC)); | ||||
|   | ||||
| @@ -23,10 +23,7 @@ | ||||
|  | ||||
| package com.iluwatar.value.object; | ||||
|  | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.Getter; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import lombok.ToString; | ||||
| import lombok.Value; | ||||
|  | ||||
| /** | ||||
|  * HeroStat is a value object. | ||||
| @@ -35,23 +32,10 @@ import lombok.ToString; | ||||
|  *     http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html | ||||
|  *     </a> | ||||
|  */ | ||||
| @Getter | ||||
| @ToString | ||||
| @EqualsAndHashCode | ||||
| @RequiredArgsConstructor | ||||
| public class HeroStat { | ||||
|  | ||||
|   // Stats for a hero | ||||
|  | ||||
|   private final int strength; | ||||
|   private final int intelligence; | ||||
|   private final int luck; | ||||
|  | ||||
|   // Static factory method to create new instances. | ||||
|   public static HeroStat valueOf(int strength, int intelligence, int luck) { | ||||
|     return new HeroStat(strength, intelligence, luck); | ||||
|   } | ||||
|  | ||||
|   // The clone() method should not be public. Just don't override it. | ||||
| @Value(staticConstructor = "valueOf") | ||||
| class HeroStat { | ||||
|  | ||||
|   int strength; | ||||
|   int intelligence; | ||||
|   int luck; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user