In which scenario can I use those design patterns in n-tier architecture?
I would advise against the data transfer object. It's an EJB 1.0 anti-pattern, in my opinion, given value by those who insist in layer purity.
A value object is useful. It's usually an immutable object, like Money. They should be thread-safe.
There are several good answers here, but I'll add one to capture a key difference:
Value objects do not have an identity. That is, any comparison between two instances of a value object that contain should indicate that they are equal. Data Transfer Objects, while only being used to hold values, do have an identity. Comparing two instances of a DTO that have the same values, but were created independently, will not indicate that they are equal.
Example:
DTO dto1 = new DTO(10);
DTO dto2 = new DTO(10);
dto1.equals(dto2); //False (if equals is not overridden)
dto1 == dto2; //False
VO vo1 = VO.getInstance(10);
VO vo2 = VO.getInstance(10);
vo1.equals(vo2); //True
vo1 == vo2; //True
It's slightly difficult to implement the Value Object pattern in Java, since the == operator always compares object identity. One way to do so would be to implement an object cache that returns the same object for each value.
public class VO {
Map<Integer, WeakReference<VO>> cache = new LinkedHashMap<Integer, WeakReference<VO>>();
public static VO getInstance(int value) {
VO cached = cache.get(value);
if(cached == null) {
cached = new VO(value);
cache.put(value, new WeakReference<VO>(cached));
}
return cached.get();
}
private int value;
private VO(int value) {
this.value = value;
}
}
Comparing DTO objects with value objects is like comparing oranges and apples.
They serve completely different situations. DTO defines the object / class structure of how data will be transferred between layers while value objects defines the logic for equality when values are compared.
Let me explain you with examples, let us first try to understand value objects first :-
Value object is an object whose equality is based on the value rather than identity.
Consider the below code we have created two objects of money one is one rupee coin and the other is a one rupee paper currency.
Money OneRupeeCoin = new Money();
OneRupeeCoin.Value = 1;
OneRupeeCoin.CurrencyType = "INR";
OneRupeeNote.Material = "Coin";
Money OneRupeeNote = new Money();
OneRupeeNote.Value = 1;
OneRupeeCoin.CurrencyType = "INR";
OneRupeeNote.Material = "Paper";
Now when you compare the above objects the below comparison should evaluate to true because 1 rupee note is equal to 1 rupee coin in real world.
So either you are using “==” operator or you are using the “Equals” method the comparison should evaluate to true. By default “==” or “equals” will not evaluate to true so you need to use operator overriding and method overriding to get the desired behavior. You can see this link which explains how to achieve the same.
if (OneRupeeCoin==OneRupeeNote)
{
Console.WriteLine("They should be equal");
}
if (OneRupeeCoin.Equals(OneRupeeNote))
{
Console.WriteLine("They should be equal ");
}
Normally value objects are good candidates for immutability; you can read more about it from here. You can see this video which describes how immutable objects can be created.
Now let’s try to understand DTO:-
DTO (Data Transfer objects) is a data container for moving simplifying data transfer between layers.
They are also termed as transfer objects. DTO is only used to pass data and does not contain any business logic. They only have simple setters and getters.
For example consider the below call we are making two calls one to get customer data and the other to get product data.
DataAccessLayer dal = new DataAccessLayer();
//Call 1:- get Customer data
CustomerBO cust = dal.getCustomer(1001);
//Call 2:- get Products for the customer
ProductsBO prod = dal.getProduct(100);
So we can combine the Customer and Product class in to one class as shown below.
class CustomerProductDTO
{
// Customer properties
public string CustomerName { get; set; }
// Product properties
public string ProductName { get; set; }
public double ProductCost { get; set; }
}
Now with one call we will be able to get both customer and product data. Data transfer objects are used in two scenarios one to improve remote calls and second to flatten object hierarchy; you can read this article which explains more about data transfer objects.
//Only one call
CustomerProductDTO cust = dal.getCustomer(1001);
Below is the complete comparison sheet.
Value Object and Data Transfer Object are design pattern.
Real world example is java.time.LocalDate
public class HeroStat {
// Stats for a hero
private final int strength;
private final int intelligence;
private final int luck;
// All constructors must be private.
private HeroStat(int strength, int intelligence, int luck) {
this.strength = strength;
this.intelligence = intelligence;
this.luck = luck;
}
// Static factory method to create new instances.
public static HeroStat valueOf(int strength, int intelligence, int luck) {
return new HeroStat(strength, intelligence, luck);
}
public int getStrength() {
return strength;
}
public int getIntelligence() {
return intelligence;
}
public int getLuck() {
return luck;
}
/*
* Recommended to provide a static factory method capable of creating an instance
from the formal
* string representation declared like this. public static HeroStat parse(String
string) {}
*/
// toString, hashCode, equals
@Override
public String toString() {
return "HeroStat [strength=" + strength + ", intelligence=" + intelligence
+ ", luck=" + luck + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + intelligence;
result = prime * result + luck;
result = prime * result + strength;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
HeroStat other = (HeroStat) obj;
if (intelligence != other.intelligence) {
return false;
}
if (luck != other.luck) {
return false;
}
if (strength != other.strength) {
return false;
}
return true;
}
// The clone() method should not be public. Just don't override it.
}
- Data Transfer Object : Pass data with multiple attributes in one shot from client to server, to avoid multiple calls to remote server.
public class CustomerDto {
private final String id;
private final String firstName;
private final String lastName;
/**
* @param id customer id
* @param firstName customer first name
* @param lastName customer last name
*/
public CustomerDto(String id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public String getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
A value object is something that is useful to encapsulate as an object, but it has no identity. Compare it to an entity, which is something that does have identity. So in an order-processing system a Customer or an Order or a LineItem are concepts that point back to specific people or things or events, so they are entities, where a value object is something like a monetary amount, that doesn't have an independent existence of its own. For instance, for a system where part of the application involved calculating how to divide a payment between different accounts, I created an immutable Money object that had a divide method that returned an array of Money objects evenly splitting the original object's amount across them, that way the code for dividing amounts was in a place that was handy where the person writing the jsp could use it, and they didn't have to mess up the jsp with non-presentation-related code.
A Data Transfer Object is a wrapper for bundling things together for sending across application tiers or layers. The idea is that you want to minimize the amount of network back-and-forth traffic by designing methods that send large bundles of information.
Data Transfer Object is used to set property values which is coming from database in Data Access Layer (DAO), whereas using VO pattern we can set values in controller layer of MVC that are already set in DAO Layer. Client can have access to VO objects rather than DTO's which he/she can iterate in jsp page. You can say there is a separation of concern for both layers.