Um DTO otimiza os dados trafegados pelo sistema, geralmente e normalmente só é útil em casos onde este tráfego é caro, como no seue xemplo de passar objetos pela rede.
Como um exemplo, imagine que eu tenha as seguintes classes no meu sistema:
class Pessoa{
private String nome;
private String CPF;
private Date dataDeNascimento;
private char sexo;
private char classeEconomica;
}
class Pedido{
private BigDecimal valorImposto;
private int codigo;
private List<Item> itensComprados; //uma lista com muuuuuuitos itens
}
E temos um cliente Swing que precisa exibir uma grande lista no formato:
| CODIGO PEDIDO | NOME CLIENTE | VALOR PEDIDO |
A primeira opção é passar objetos das classes acima via RMI ou algo parecido para o cliente. Após alguns testes verificamos que isso é muito custovo (serializar, passar os bytes, restauras, etc) e já que precisamos apenas de alguns destes dados nós criamos um DataTransferObject que faz apenas isso:
class PedidoPorClienteDTO{
int codigoPedido;
String nomeCliente;
BigDecimal valorotalPedido;
}
Quando o cliente Swing pede estes dados o servidor cria os objetos da classe PedidoPorClienteDTO e os popula com dados das classes ‘de verdade’. Isso é um DTO.