Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism and DTO object creation

Tags:

java

dto

I develop application which contains few tiers. We have DAO layer which returns model objects. We also have mappers which instantiate DTO objects and send them to clients. Entities are mapped to DTOs in Controller layer. I've introduced inheritance in few entity classes. Let's assume sth like on image below

class diagram (not enough reputation points to past image directly)

I ask DAO for list of animals from the concrete ZOO. Then I get list List animals, but they are of concrete type because Animal is abstract and we cannot have just Animal in the database. I would like to create DTOs from this model objects. I have to use mapper in which I have if .. else statements checking type of each animal and then creating proper DTO, sth like

if (animal instanceof Dog) {
  .. create dog dto
} else if (animal instance of Cat) {
  .. create cat dto
} .. and so on

This code does not look nice. It would be nice to use polymorphism and call some method on each animal to produce DTO, but it is bad to have logic in domain model creating DTO objects just to communication. How do you resolve such situations?

Edit: To be more specific, I want to have DTO like 1. DogDTO which contains only fields color and name 2. FishDTO which contains only numberOfFins Not one big AnimalDTO with all possible attributes

like image 526
soulcoder Avatar asked May 29 '15 11:05

soulcoder


1 Answers

You want to select a different transformation for a different type of object. Basically there are two approaches to this problem in Java:

  1. Use the instanceof or map the Class of the object to a specialized Transformer object by getting it from a repository (could be simple Map<Class, Transfomer>). This is the approach that the frameworks suggested here use.

  2. Use the visitor pattern. The idea of this approach is that the simplest approach would be to have a toDTO() method in all of your domain objects, but this would introduce an unwanted dependency in your domain objects on your DTO's. Another approach would be to have all these classes in a single object toDTO(Dog d) toDTO(Fish f), but unfortunately the single-dispatch feature in Java means that to be able to use this, you would still have to figure out the type of the object you want to transform and call the right method: the VM cannot do this for you. The Visitor pattern is a design pattern that solves this problem.

The basic design of the visitor pattern is like this:

public abstract class AnimalVisitor<T> {

  public abstract T visit (Dog d);

  public abstract T visit (Fish f);

  ...

}

public abstract class Animal {

  public <T> abstract T accept (AnimalVisitor<T> v);

  ...

}

public class Dog extends Animal {

  public <T> T accept (AnimalVisitor<T> v) {
    return v.visit(this);
  }

  ...

}

public class Fish extends Animal {

  public <T> T accept (AnimalVisitor<T> v) {
    return v.visit(this);
  }

  ...

}

public class DTOTransformer extends AnimalVisitor<DTO> {

  public DogDTO visit (Dog d) {
    return new DogDTO(d);
  }

  public FishDTO visit (Fish f) {
    return new FishDTO(f);
  }

}

When you introduce a new Animal type, you need to add a new visit method to the AnimalVisitor class. You will be prompted to do this, since you will have to implement the accept method in the new Animal type. This will also prompt you to update the DTOTransformer and any other implementations of the AnimalVisitor.

As you can see, this approach requires a lot more code then the simple instanceof style approach. It does provide you with a nice extendable mechanisme for other similar operations you would want to do on your domain.

I guess it really depends on your situation which approach is best. I would, however, always recommend using a framework like Dozer or ModdelMapper over writing the if (.. instanceof ...) else if (... myself.

like image 187
Maarten Winkels Avatar answered Nov 15 '22 00:11

Maarten Winkels