How can I Make a Successful Domain Object Factory

2019-03-31 06:06发布

问题:

I'm fiddling with an MVC framework, and I stumbled upon a problem I'm not sure how to solve.

I want to make a DomainObjectFactory for the Model layer of my application, however, each Domain object would have a different set of arguments, for instance:

  • Person - $id, $name, $age.
  • Post - $id, $author, $title, $content, $comments
  • Comment - $id, $author, $content

And so on. How can I easily tell my factory what kinds of object do I require?

I've came up with several options:

  • Pass an array - I dislike this one, because you can't rely on the constructor's contract to tell what the object needs for his work.
  • Make the DomainObjectFactory an interface, and make concrete classes - Problematic, because that's an awful lot of factories to make!
  • Use Reflection - Service locator much? I don't know, it just seems that way to me.

Is there a useful deign pattern I can employ here? Or some other clever solution?

回答1:

Why do you want to initialize a Domain Object with all the properties assigned?

Instead just create an empty Domain Object. You might in the factory check, if it has prepare() method to execute. Oh .. and if you are using DAO, instead of directly interacting with Mappers, you might want to construct and inject the appropriate DAO in your Domain Object.

The assignment of values should just happen in the Service. By the use of ordinary setters.

Some examples:

Retrieving existing article

public function retrieveArticle( $id )
{
    $mapper = $this->mapperFactory->create('Article');
    $article = $this->domainFactory->create('Article');

    $article->setId( $id );
    $mapper->fetch( $article );
    $this->currentArticle = $article;
}

Posting new comment

public function addComment( $id, $content )
{

    $mapper = $this->mapperFactory->create('article');
    $article = $this->domainFactory->create('Article');
    $comment = $this->domainFactory->create('Comment');

    $comment->setContent( $content );
    $comment->setAuthor( /* user object that you retrieved from Recognition service */ );

    $article->setId( $id );
    $article->addComment( $comment );
    // or you might retrieve the ID of currently view article
    // and assign it .. depends how you build it all

    $mapper->store( $article ); // or 
}

Passing user input

public function getArticle( $request )
{
    $library = $this->serviceFactory->build('Library');
    $library->retrieveArticle( $request->getParameter('articleId'));
}