Skip to content

Commit

Permalink
#1569 DTO pattern implementation using Enums (#1570)
Browse files Browse the repository at this point in the history
* #1569 DTO pattern implemented using Enums

* #1569 DTO pattern implemented using Enums

* #1569 adding some java docs

* #1569 some changes in java doc and code style

* #1569 some changes in java doc and code style

* #1569 some changes in java doc and code style

* #1569 some changes in java doc and code style

* #1569 adding suggested extra line

* #1569 license added to pom.xml

* #1569 more checkstyle problems resolved

* #1569 more checkstyle problems resolved

* #1569 more checkstyle problems resolved

Co-authored-by: siavashsoleymani <siavash.soleimani@snapp.cab>
Co-authored-by: Subhrodip Mohanta <subhrodipmohanta@gmail.com>
  • Loading branch information
3 people committed Dec 9, 2020
1 parent a94615a commit 5bc61c8
Show file tree
Hide file tree
Showing 10 changed files with 774 additions and 0 deletions.
54 changes: 54 additions & 0 deletions data-transfer-object-enum-impl/README.md
@@ -0,0 +1,54 @@
---
layout: pattern
title: Data Transfer Object
folder: data-transfer-object
permalink: /patterns/data-transfer-object/
categories: Architectural
tags:
- Performance
---

## Intent

Pass data with multiple attributes in one shot from client to server, to avoid multiple calls to
remote server.

## Explanation

Real world example

> We need to fetch information about customers from remote database. Instead of querying the
> attributes one at a time, we use DTOs to transfer all the relevant attributes in a single shot.
In plain words

> Using DTO relevant information can be fetched with a single backend query.
Wikipedia says

> In the field of programming a data transfer object (DTO) is an object that carries data between
> processes. The motivation for its use is that communication between processes is usually done
> resorting to remote interfaces (e.g. web services), where each call is an expensive operation.
> Because the majority of the cost of each call is related to the round-trip time between the client
> and the server, one way of reducing the number of calls is to use an object (the DTO) that
> aggregates the data that would have been transferred by the several calls, but that is served by
> one call only.
## Class diagram

![alt text](./etc/dto-enum-uml.png "data-transfer-object")

## Applicability

Use the Data Transfer Object pattern when:

* The client is asking for multiple information. And the information is related.
* When you want to boost the performance to get resources.
* You want reduced number of remote calls.

## Credits

* [Design Pattern - Transfer Object Pattern](https://www.tutorialspoint.com/design_pattern/transfer_object_pattern.htm)
* [Data Transfer Object](https://msdn.microsoft.com/en-us/library/ff649585.aspx)
* [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)
* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321127420&linkCode=as2&tag=javadesignpat-20&linkId=014237a67c9d46f384b35e10151956bd)
@@ -0,0 +1,129 @@
@startuml
package com.iluwatar.datatransferenum {
class App {
- LOGGER : Logger {static}
+ App()
+ main(args : String[]) {static}
}
class Product {
- cost : Double
- id : Long
- name : String
- price : Double
- supplier : String
+ Product()
+ getCost() : Double
+ getId() : Long
+ getName() : String
+ getPrice() : Double
+ getSupplier() : String
+ setCost(cost : Double) : Product
+ setId(id : Long) : Product
+ setName(name : String) : Product
+ setPrice(price : Double) : Product
+ setSupplier(supplier : String) : Product
+ toString() : String
}
enum ProductDTO {
+ valueOf(name : String) : ProductDTO {static}
+ values() : ProductDTO[] {static}
}
-interface Cost {
+ getCost() : Double {abstract}
}
-interface Id {
+ getId() : Long {abstract}
}
-interface Name {
+ getName() : String {abstract}
}
-interface Price {
+ getPrice() : Double {abstract}
}
enum Request {
+ valueOf(name : String) : Request {static}
+ values() : Request[] {static}
}
class Create {
- cost : Double
- name : String
- price : Double
- supplier : String
+ Create()
+ getCost() : Double
+ getName() : String
+ getPrice() : Double
+ getSupplier() : String
+ setCost(cost : Double) : Create
+ setName(name : String) : Create
+ setPrice(price : Double) : Create
+ setSupplier(supplier : String) : Create
}
enum Response {
+ valueOf(name : String) : Response {static}
+ values() : Response[] {static}
}
class Private {
- cost : Double
- id : Long
- name : String
- price : Double
+ Private()
+ getCost() : Double
+ getId() : Long
+ getName() : String
+ getPrice() : Double
+ setCost(cost : Double) : Private
+ setId(id : Long) : Private
+ setName(name : String) : Private
+ setPrice(price : Double) : Private
+ toString() : String
}
class Public {
- id : Long
- name : String
- price : Double
+ Public()
+ getId() : Long
+ getName() : String
+ getPrice() : Double
+ setId(id : Long) : Public
+ setName(name : String) : Public
+ setPrice(price : Double) : Public
+ toString() : String
}
-interface Supplier {
+ getSupplier() : String {abstract}
}
class ProductResource {
- products : List<Product>
+ ProductResource(products : List<Product>)
+ getAllProductsForAdmin() : List<Private>
+ getAllProductsForCustomer() : List<Public>
+ getProducts() : List<Product>
+ save(createProductDTO : Create)
}
}
Create ..+ Request
Request ..+ ProductDTO
Private ..+ Response
Supplier ..+ ProductDTO
Name ..+ ProductDTO
ProductResource --> "-products" Product
Public ..+ Response
Id ..+ ProductDTO
Price ..+ ProductDTO
Response ..+ ProductDTO
Cost ..+ ProductDTO
Create ..|> Name
Create ..|> Price
Create ..|> Cost
Create ..|> Supplier
Private ..|> Id
Private ..|> Name
Private ..|> Price
Private ..|> Cost
Public ..|> Id
Public ..|> Name
Public ..|> Price
@enduml
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 61 additions & 0 deletions data-transfer-object-enum-impl/pom.xml
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright © 2014-2019 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.24.0-SNAPSHOT</version>
</parent>
<artifactId>data-transfer-object-enum-impl</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.datatransferenum.App</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,59 @@
package com.iluwatar.datatransferenum;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The Data Transfer Object pattern is a design pattern in which an data transfer object is used to
* serve related information together to avoid multiple call for each piece of information.
*
* <p>In this example, ({@link App}) as as product details consumer i.e. client to
* request for product details to server.
*
* <p>productResource ({@link ProductResource}) act as server to serve product information. And
* The productDto ({@link ProductDto} is data transfer object to share product information.
*/
public class App {

private static final Logger LOGGER = LoggerFactory.getLogger(App.class);

/**
* Method as act client and request to server for details.
*
* @param args program argument.
*/
public static void main(String[] args) {
Product tv =
new Product().setId(1L).setName("TV").setSupplier("Sony").setPrice(1000D).setCost(1090D);
Product microwave =
new Product().setId(2L).setName("microwave").setSupplier("Delonghi").setPrice(1000D)
.setCost(1090D);
Product refrigerator =
new Product().setId(3L).setName("refrigerator").setSupplier("Botsch").setPrice(1000D)
.setCost(1090D);
Product airConditioner =
new Product().setId(4L).setName("airConditioner").setSupplier("LG").setPrice(1000D)
.setCost(1090D);
List<Product> products =
new ArrayList<>(Arrays.asList(tv, microwave, refrigerator, airConditioner));
ProductResource productResource = new ProductResource(products);

LOGGER.info("####### List of products including sensitive data just for admins: \n {}",
Arrays.toString(productResource.getAllProductsForAdmin().toArray()));
LOGGER.info("####### List of products for customers: \n {}",
Arrays.toString(productResource.getAllProductsForCustomer().toArray()));

LOGGER.info("####### Going to save Sony PS5 ...");
ProductDto.Request.Create createProductRequestDto = new ProductDto.Request.Create()
.setName("PS5")
.setCost(1000D)
.setPrice(1220D)
.setSupplier("Sony");
productResource.save(createProductRequestDto);
LOGGER.info("####### List of products after adding PS5: {}",
Arrays.toString(productResource.getProducts().toArray()));
}
}
@@ -0,0 +1,91 @@
package com.iluwatar.datatransferenum;

/**
* {@link Product} is a entity class for product entity. This class act as entity in the demo.
*/
public final class Product {
private Long id;
private String name;
private Double price;
private Double cost;
private String supplier;

/**
* Constructor.
*
* @param id product id
* @param name product name
* @param price product price
* @param cost product cost
* @param supplier product supplier
*/
public Product(Long id, String name, Double price, Double cost, String supplier) {
this.id = id;
this.name = name;
this.price = price;
this.cost = cost;
this.supplier = supplier;
}

/**
* Constructor.
*/
public Product() {
}

public Long getId() {
return id;
}

public Product setId(Long id) {
this.id = id;
return this;
}

public String getName() {
return name;
}

public Product setName(String name) {
this.name = name;
return this;
}

public Double getPrice() {
return price;
}

public Product setPrice(Double price) {
this.price = price;
return this;
}

public Double getCost() {
return cost;
}

public Product setCost(Double cost) {
this.cost = cost;
return this;
}

public String getSupplier() {
return supplier;
}

public Product setSupplier(String supplier) {
this.supplier = supplier;
return this;
}

@Override
public String toString() {
return "Product{"
+ "id=" + id
+ ", name='" + name + '\''
+ ", price=" + price
+ ", cost=" + cost
+ ", supplier='" + supplier + '\''
+ '}';
}
}

0 comments on commit 5bc61c8

Please sign in to comment.