Friday, April 27, 2012

Decoupling Domain Objects

Overview

Given a top down design where the domain objects do not match the entity objects, one of the common techniques in object oriented design is to decouple the object layers. One decoupling technique is to use composite objects. Each level of abstraction will utilize its own composite object (Domain and View). It seems like a lot to write from the looks of it but most IDE supports creations of delegate methods now anyways.

Components

Service Layer, Persistent Object, Domain Object, View Object


Service Layer

public interface BlogManager {
    Blog load(String name) throws EntityNotFoundException;
}

public class BlogManagerImpl implements BlogManager {
    // Fictitious EntityManager
    EntityManager em;

    public Blog load(String name) throws EntityNotFoundException {
        Blog blog = null;
        BlogData data = em.query("select b from BlogData b where b.name = ?", name);
        return new Blog(data);
    }
}

Persistent Object

BlogData: an entity-managed persistent object (managed by hibernate for example)
@Peristent
public class BlogData {

   private String name;

   public String getName() {
      return name;
   }

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

Domain

Blog (First-class citizen)
public class Blog {
    private BlogData delegate;

    public Blog(BlogData delegate) {
        this.delegate = delegate;
    }

    // Example delegate methods
    public getName() {
        return delegate.getName();
    }

    public BlogData getData() {
        return delegate;
    }
}

View Object

public class BlogBean {

    private Blog delegate;

    public BlogBean(Blog delegate) {
        this.delegate = delegate;
    }

    public String getName() {
        return delegate.getName();
    }

    // custom UI method

    public boolean isActive() {
        // custom code (UI Logic)
    }
}

Example Controller

@Controller
public class BlogController {

    @RequestMapping("/getBlog")
    public void getBlog(String name) {
        ModelMap model = new ModelMap();
        BlogBean blog = blogManager.load(name);
        model.addAttribute("blog", blog);
    }

}


No comments: