Разница между шаблоном объекта значения и шаблоном передачи данных - PullRequest
7 голосов
/ 08 августа 2011

В каком сценарии я могу использовать эти шаблоны проектирования в многоуровневой архитектуре?

Ответы [ 8 ]

13 голосов
/ 08 августа 2011

DTO - это объект, который вы можете использовать на границах системы. Например, если у вас есть веб-служба SOAP и вы хотите вернуть ответ, вы должны использовать DTO. С ним легче иметь дело, чем с реальным XML, который должен быть возвращен по сети. DTO часто генерируются инструментами, например, на основе WSDL. DTO часто адаптированы к потребностям потребителя услуг и могут зависеть от требований к производительности.

С другой стороны, объекты-значения живут в ядре системы. Он фиксирует части бизнес-логики и, возможно, правила форматирования. Это делает ваш код более безопасным и выразительным. Это также решает проблему «примитивной одержимости» анти-паттерном. Хорошим примером является использование класса «SocialSecurityNumber» вместо строки. Или деньги вместо десятичной. Эти объекты должны быть неизменными, чтобы они больше походили на примитивы и могли быть легко распределены между различными потоками.

Например, в гипотетической системе «заказ клиента»:

CustomerAndLastFiveOrders - это DTO (оптимизировано для избежания множественных сетевых вызовов)

Клиент является юридическим лицом

Деньги и SKU являются объектами Value

8 голосов
/ 09 ноября 2015

Сравнение объектов DTO с объектами-значениями похоже на сравнение апельсинов и яблок.

Они обслуживают совершенно разные ситуации. DTO определяет структуру объекта / класса того, как данные будут передаваться между слоями, а объекты-значения определяют логику равенства при сравнении значений.

enter image description here

Позвольте мне объяснить вам примеры, давайте сначала попробуем понять объекты-значения: -

Объект значения - это объект, равенство которого основано скорее на значении чем личность.

Рассмотрим приведенный ниже код: мы создали два объекта денег: один - одна монета рупии, а другой - одна бумажная валюта рупии.

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";

Теперь, когда вы сравниваете вышеперечисленные объекты, приведенное ниже сравнение должно быть истинным, потому что 1 реальная рупия равна 1 рупийной монете в реальном мире.

То есть, вы используете оператор «==» или метод «Равно», и сравнение должно оцениваться как true. По умолчанию «==» или «равно» не будут иметь значение true, поэтому вам нужно использовать переопределение оператора и переопределение метода, чтобы получить желаемое поведение. Вы можете увидеть эту ссылку , которая объясняет, как этого добиться.

if (OneRupeeCoin==OneRupeeNote)
 {
 Console.WriteLine("They should be equal");
 }
if (OneRupeeCoin.Equals(OneRupeeNote))
 {
 Console.WriteLine("They should be equal ");
 }

Обычно значения объектов являются хорошими кандидатами на неизменность; Вы можете прочитать больше об этом из здесь . Вы можете увидеть это видео , в котором описано, как можно создавать неизменяемые объекты.

Теперь давайте попробуем понять DTO: -

DTO (объекты передачи данных) - это контейнер данных для упрощения перемещения передача данных между слоями.

Они также называются объектами передачи. DTO используется только для передачи данных и не содержит никакой бизнес-логики. У них есть только простые сеттеры и геттеры.

Например, рассмотрим приведенный ниже вызов. Мы делаем два вызова: один для получения данных о клиентах, а другой - для получения данных о продукте.

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);

Таким образом, мы можем объединить класс Customer и Product в один класс, как показано ниже.

class CustomerProductDTO
{
  // Customer properties
        public string CustomerName { get; set; }
   // Product properties
        public string ProductName { get; set; }
        public double ProductCost { get; set; }
}

Теперь с помощью одного звонка мы сможем получить данные о клиентах и ​​продуктах. Объекты передачи данных используются в двух сценариях: один - для улучшения удаленных вызовов, а второй - для выравнивания иерархии объектов; Вы можете прочитать эту статью , которая объясняет больше об объектах передачи данных.

//Only one call
CustomerProductDTO cust = dal.getCustomer(1001);

Ниже приведен полный лист сравнения.

enter image description here

3 голосов
/ 08 августа 2011

Здесь есть несколько хороших ответов, но я добавлю один, чтобы зафиксировать ключевое отличие:

Объекты-значения не имеют идентичности. То есть любое сравнение между двумя экземплярами объекта-значения, которые содержат, должно указывать, что они равны. Объекты передачи данных, хотя и используются только для хранения значений, имеют идентичность. Сравнение двух экземпляров DTO, которые имеют одинаковые значения, но были созданы независимо, не покажет, что они равны.

Пример:

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

Немного сложно реализовать шаблон Value Object в Java, так как оператор == всегда сравнивает идентичность объекта. Один из способов сделать это - реализовать кэш объектов, который возвращает один и тот же объект для каждого значения.

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;
  }
}
2 голосов
/ 08 августа 2011

Объект-значение - это то, что полезно инкапсулировать как объект, но у него нет идентификатора.Сравните это с сущностью, которая имеет идентичность.Таким образом, в системе обработки заказов Клиент, Заказ или LineItem являются понятиями, которые указывают на конкретных людей или вещи или события, поэтому они являются сущностями, где объект стоимости - это что-то вроде денежной суммы, которая не имеетсамостоятельное существование своего.Например, для системы, в которой часть приложения включала вычисление того, как разделить платеж между различными счетами, я создал неизменяемый объект Money, у которого был метод деления, который возвращал массив объектов Money, равномерно распределяющих сумму исходного объекта по ним, чтотаким образом, код для деления сумм находился в удобном месте, где человек, пишущий jsp, мог его использовать, и ему не нужно было путать jsp с кодом, не связанным с представлением.

A ДанныеTransfer Object - это оболочка для объединения вещей для отправки между уровнями или уровнями приложения.Идея состоит в том, что вы хотите минимизировать объем двустороннего сетевого трафика путем разработки методов, которые отправляют большие пакеты информации.

2 голосов
/ 08 августа 2011

Я бы посоветовал против объекта передачи данных.На мой взгляд, это анти-паттерн EJB 1.0, данный ценностью тех, кто настаивает на чистоте слоя.

Полезен объект значения.Обычно это неизменный объект, такой как деньги.Они должны быть поточно-ориентированными.

1 голос
/ 08 октября 2018

DTO - это класс, представляющий некоторые данные без какой-либо логики.DTO обычно используются для передачи данных между разными приложениями или разными уровнями в одном приложении.Вы можете рассматривать их как глупые пакеты информации, единственной целью которых является просто передать эту информацию получателю.

С другой стороны, Объект значения является полноправным членом вашей организации.доменная модель.Он соответствует тем же правилам, что и сущность.Единственное различие между Value Object и Entity заключается в том, что Value Object не имеет собственной идентичности.Это означает, что два объекта значения с одинаковым набором свойств следует считать одинаковыми, тогда как два объекта отличаются, даже если их свойства совпадают.

Объекты значения содержат логику и, как правило, они не используются для передачи данных между приложениямиграницы.Подробнее здесь

1 голос
/ 28 июля 2017

Объект передачи данных используется для установки значений свойств, которые поступают из базы данных на уровне доступа к данным (DAO), тогда как с помощью шаблона VO мы можем установить значения на уровне контроллера MVC, которые уже установлены на уровне DAO. Клиент может иметь доступ к объектам VO, а не к DTO, которые он / она может перебирать на странице JSP. Вы можете сказать, что существует разделение проблем для обоих слоев.

0 голосов
/ 03 мая 2019

Объект значения и объект передачи данных являются шаблоном проектирования.

  • Объект значения : Используйте, когда необходимо измерить равенство объектов на основе значения объектов.

Пример реального мира - 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.
  }

- Объект передачи данных : передача данных с несколькими атрибутами за один снимок с клиента на сервер, чтобы избежать нескольких вызовов на удаленный сервер.

  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;
        }
     }
...