Java中的数据传输对象设计模式(Data Transfer Object Design Pattern)


数据传输对象设计模式是一种经常使用的设计模式。它主要用于从客户端到服务器一次性传递具有多个属性的数据,以避免多次调用远程服务器。
目的
从客户端到服务器一次性传递具有多个属性的数据,以避免多次调用远程服务器。

问题
您希望跨层传输多个数据元素。

动机
您希望客户端访问其他层中的组件以检索和更新数据。
您希望减少网络上的远程请求。
您希望避免由流量高的聊天应用程序而导致的网络性能下降

解决方案
使用传输对象跨层传输多个数据元素。

说明

  • 数据传输对象模式是一种设计模式,数据传输对象将相关信息一起提供,以避免对每条信息进行多次调用。
  • Transfer Object是一个简单的POJO类,具有getter / setter方法,并且是可序列化的,因此可以通过网络传输。它没有任何行为。
  • 服务器端业务类通常从数据库中提取数据并填充POJO并将其发送到客户端或按值传递。对于客户端,传输对象是只读的。
  • 客户端可以创建自己的传输对象并将其传递给服务器,以便一次性更新数据库中的值。

维基百科说
数据传输对象是在进程之间传输数据的对象。其使用的动机是进程之间的通信通常采用远程接口(例如,Web服务),其中每个调用都是代价不菲的操作。[因为每个调用的大部分成本都与客户端和服务器之间的往返时间有关,减少调用数量的一种方法是使用一个对象(DTO)它聚集了几个调用可能传输的数据,但只由一个调用提供服务。

结构
让我们使用UML类图来展示解决方案的基本结构,本节中的UML序列图介绍了解决方案的动态机制。 
下面是表示数据传输对象设计模式的关系的类图和序列图。

类图

序列图

执行
第1步: CustomerDto是数据传输对象POJO。而不是向客户端发送个人信息。我们可以在一个POJO类中一起发送相关信息。请注意,DTO中没有任何业务逻辑。

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 name name 
/ / public CustomerDto( String id, String firstName, String lastName){
         this 。id = id;
        这个。firstName = firstName;
        这个。lastName = lastName;     
        
    }

    public  String  getId(){
         return id;
    }

    public  String  getFirstName(){
         return firstName;
    }

    public  String  getLastName(){
         return lastName;
    }
}

第2步:  创建一个服务客户信息的资源类。该类充当演示中的服务器。客户详细信息在哪儿?

public class CustomerResource {
    private List < CustomerDto > customers;

    /**
     * @param customers initialize resource with existing customers. Act as database.
     */

    public CustomerResource(List < CustomerDto > customers) {
        this.customers = customers;
    }

   
/**
     * @return : all customers in list.
     */

    public List < CustomerDto > getAllCustomers() {
        return customers;
    }

   
/**
     * @param customer save new customer to list.
     */

    public void save(CustomerDto customer) {
        customers.add(customer);
    }

   
/**
     * @param customerId delete customer with id {@code customerId}
     */

    public void delete(String customerId) {
        customers.removeIf(customer - > customer.getId().equals(customerId));
    }
}

第3步: CustomerClientApp类是客户详细信息使用者,即客户端向服务器请求客户详细信息。

  • CustomerResource充当服务器来提供客户信息。
  • customerdto是用于共享客户信息的数据传输对象。

public class CustomerClientApp {

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

    /**
     * Method as act client and request to server for details.
     *
     * @param args program argument.
     */

    public static void main(String[] args) {
        List < CustomerDto > customers = new ArrayList < > ();
        CustomerDto customerOne = new CustomerDto(
"1", "Kelly", "Brown");
        CustomerDto customerTwo = new CustomerDto(
"2", "Alfonso", "Bass");
        customers.add(customerOne);
        customers.add(customerTwo);

        CustomerResource customerResource = new CustomerResource(customers);

        LOGGER.info(
"All customers:-");
        List < CustomerDto > allCustomers = customerResource.getAllCustomers();
        printCustomerDetails(allCustomers);

        LOGGER.info(
"----------------------------------------------------------");

        LOGGER.info(
"Deleting customer with id {1}");
        customerResource.delete(customerOne.getId());
        allCustomers = customerResource.getAllCustomers();
        printCustomerDetails(allCustomers);

        LOGGER.info(
"----------------------------------------------------------");

        LOGGER.info(
"Adding customer three}");
        CustomerDto customerThree = new CustomerDto(
"3", "Lynda", "Blair");
        customerResource.save(customerThree);
        allCustomers = customerResource.getAllCustomers();
        printCustomerDetails(allCustomers);
    }

    private static void printCustomerDetails(List < CustomerDto > allCustomers) {
        allCustomers.forEach(customer - > LOGGER.info(customer.getFirstName()));
    }
}

结果

  • 减少网络流量
  • 简化远程对象和远程接口
  • 在更少的远程调用中传输更多数据
  • 减少代码重复
  • 引入陈旧的转移对象
  • 由于同步和版本控制而增加了复杂性。

适用场景

  • 客户要求提供多种信息。而且信息是相关的。
  • 当你想提高性能以获取资源时。
  • 您希望减少远程呼叫的数量。