Skip to content

Commit d6d2a76

Browse files
committed
docs: update value object
1 parent 8dd3e3e commit d6d2a76

File tree

3 files changed

+62
-30
lines changed

3 files changed

+62
-30
lines changed

value-object/README.md

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,45 @@ title: Value Object
33
category: Creational
44
language: en
55
tag:
6-
- Instantiation
6+
- Data binding
7+
- Domain
8+
- Encapsulation
9+
- Immutable
710
---
811

12+
## Also known as
13+
14+
* Immutable Object
15+
916
## Intent
1017

11-
Provide objects which follow value semantics rather than reference semantics.
12-
This means value objects' equality is not based on identity. Two value objects are
13-
equal when they have the same value, not necessarily being the same object.
18+
To create immutable objects that represent a descriptive aspect of the domain with no conceptual identity.
1419

1520
## Explanation
1621

1722
Real-world example
1823

19-
> There is a class for hero statistics in a role-playing game. The statistics contain attributes
20-
> such as strength, intelligence, and luck. The statistics of different heroes should be equal
21-
> when all the attributes are equal.
24+
> Consider the case of a business card. In the real world, a business card contains information such as the person's name, job title, phone number, and email address. This information represents a specific and complete set of attributes describing the contact details of an individual but doesn't have an identity itself beyond this information.
25+
>
26+
> In a software system, you can create a `BusinessCard` class as a Value Object. This class would be immutable, meaning once a `BusinessCard` object is created with a person's details, those details cannot change. If you need a different business card, you create a new instance rather than modifying the existing one. The equality of two `BusinessCard` objects would be based on their contained data rather than their memory addresses, ensuring that two business cards with the same details are considered equal. This mirrors how business cards in real life are used and compared based on their content, not on the physical card itself.
2227
2328
In plain words
2429

25-
> Value objects are equal when their attributes have the same value
30+
> Value objects are equal when their attributes have the same value.
2631
2732
Wikipedia says
2833

29-
> In computer science, a value object is a small object that represents a simple entity whose
30-
> equality is not based on identity: i.e. two value objects are equal when they have the same
31-
> value, not necessarily being the same object.
34+
> 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.
3235
3336
**Programmatic Example**
3437

35-
Here is the `HeroStat` class that is the value object. Notice the use of
36-
[Lombok's `@Value`](https://projectlombok.org/features/Value) annotation.
38+
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.
39+
40+
Here is the `HeroStat` class that is the value object. Notice the use of [Lombok's `@Value`](https://projectlombok.org/features/Value) annotation.
3741

3842
```java
3943
@Value(staticConstructor = "valueOf")
44+
@ToString
4045
class HeroStat {
4146

4247
int strength;
@@ -52,12 +57,12 @@ var statA = HeroStat.valueOf(10, 5, 0);
5257
var statB = HeroStat.valueOf(10, 5, 0);
5358
var statC = HeroStat.valueOf(5, 1, 8);
5459

55-
LOGGER.info(statA.toString());
56-
LOGGER.info(statB.toString());
57-
LOGGER.info(statC.toString());
60+
LOGGER.info("statA: {}", statA);
61+
LOGGER.info("statB: {}", statB);
62+
LOGGER.info("statC: {}", statC);
5863

59-
LOGGER.info("Is statA and statB equal : {}", statA.equals(statB));
60-
LOGGER.info("Is statA and statC equal : {}", statA.equals(statC));
64+
LOGGER.info("Are statA and statB equal? {}", statA.equals(statB));
65+
LOGGER.info("Are statA and statC equal? {}", statA.equals(statC));
6166
```
6267

6368
Here's the console output.
@@ -72,24 +77,49 @@ Here's the console output.
7277

7378
## Class diagram
7479

75-
![alt text](./etc/value-object.png "Value Object")
80+
![Value Object](./etc/value-object.png "Value Object")
7681

7782
## Applicability
7883

7984
Use the Value Object when
8085

81-
* The object's equality needs to be based on the object's value
86+
* When representing a set of attributes that together describe an entity but without an identity.
87+
* When the equality of the objects is based on the value of the properties, not the identity.
88+
* When you need to ensure that objects cannot be altered once created.
8289

8390
## Known uses
8491

92+
* Implementing complex data types like monetary values, measurements, and other domain-specific values.
8593
* [java.util.Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)
8694
* [java.time.LocalDate](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html)
95+
* [java.awt.Color](https://docs.oracle.com/javase/8/docs/api/java/awt/Color.html)
8796
* [joda-time, money, beans](http://www.joda.org/)
8897

98+
## Consequences
99+
100+
Benefits:
101+
102+
* Simplifies code by making objects immutable.
103+
* Thread-safe as the object's state cannot change after creation.
104+
* Easier to reason about and maintain.
105+
106+
Trade-offs:
107+
108+
* Creating a new object for every change can be less efficient for complex objects.
109+
* Increased memory usage due to the creation of multiple objects representing different states.
110+
111+
## Related Patterns
112+
113+
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Often used to create instances of value objects.
114+
* [Builder](https://java-design-patterns.com/patterns/builder/): Can be used to construct complex value objects step by step.
115+
* [Prototype](https://java-design-patterns.com/patterns/prototype/): Can be used to clone existing value objects, though cloning is less common with immutable objects.
116+
89117
## Credits
90118

91-
* [Patterns of Enterprise Application Architecture](http://www.martinfowler.com/books/eaa.html)
92-
* [ValueObject](https://martinfowler.com/bliki/ValueObject.html)
93-
* [VALJOs - Value Java Objects : Stephen Colebourne's blog](http://blog.joda.org/2014/03/valjos-value-java-objects.html)
119+
* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)
120+
* [Effective Java](https://amzn.to/4cGk2Jz)
121+
* [J2EE Design Patterns](https://amzn.to/4dpzgmx)
122+
* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)
123+
* [ValueObject - Martin Fowler](https://martinfowler.com/bliki/ValueObject.html)
124+
* [VALJOs - Value Java Objects: Stephen Colebourne](http://blog.joda.org/2014/03/valjos-value-java-objects.html)
94125
* [Value Object : Wikipedia](https://en.wikipedia.org/wiki/Value_object)
95-
* [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)

value-object/src/main/java/com/iluwatar/value/object/App.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
/**
3030
* A Value Object are objects which follow value semantics rather than reference semantics. This
3131
* means value objects' equality are not based on identity. Two value objects are equal when they
32-
* have the same value, not necessarily being the same object..
32+
* have the same value, not necessarily being the same object.
3333
*
3434
* <p>Value Objects must override equals(), hashCode() to check the equality with values. Value
3535
* Objects should be immutable so declare members final. Obtain instances by static factory methods.
@@ -51,11 +51,11 @@ public static void main(String[] args) {
5151
var statB = HeroStat.valueOf(10, 5, 0);
5252
var statC = HeroStat.valueOf(5, 1, 8);
5353

54-
LOGGER.info(statA.toString());
55-
LOGGER.info(statB.toString());
56-
LOGGER.info(statC.toString());
54+
LOGGER.info("statA: {}", statA);
55+
LOGGER.info("statB: {}", statB);
56+
LOGGER.info("statC: {}", statC);
5757

58-
LOGGER.info("Is statA and statB equal : {}", statA.equals(statB));
59-
LOGGER.info("Is statA and statC equal : {}", statA.equals(statC));
58+
LOGGER.info("Are statA and statB equal? {}", statA.equals(statB));
59+
LOGGER.info("Are statA and statC equal? {}", statA.equals(statC));
6060
}
6161
}

value-object/src/main/java/com/iluwatar/value/object/HeroStat.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package com.iluwatar.value.object;
2626

27+
import lombok.ToString;
2728
import lombok.Value;
2829

2930
/**
@@ -34,6 +35,7 @@
3435
* </a>
3536
*/
3637
@Value(staticConstructor = "valueOf")
38+
@ToString
3739
class HeroStat {
3840

3941
int strength;

0 commit comments

Comments
 (0)