这是一个很好的工厂候选人吗?

Dec*_*ler 7 php design-patterns factory

我想创建一个投票系统,可以对多个域对象进行投票:

  • 日历活动
  • 一条评论
  • 一个用户

所以我想我会Voteable为这些项创建一个接口:

interface Voteable
{
    public function vote( User $user, $value );
}
Run Code Online (Sandbox Code Playgroud)

我认为这个vote方法会代理一个存储库方法,例如:

class VotingRepository
{
    public function castVote( Voteable $item, User $user, $value )
    {
        // save the these values, along with the value
        $itemId = $item->getId();
        $userId = $user->getId();

    }
}
Run Code Online (Sandbox Code Playgroud)

目前,存储库将是一个数据库.该数据库将具有每种投票类型的链接表:

  • eventVote
  • commentVote
  • userVote

因此,这实际上意味着每个域对象都需要另一个表来投票.这对工厂来说是个好人吗?一个VotingRepositoryFactory在这种情况下?换句话说,像:

class VotingRepositoryFactory
{
    createVotingRepository( $type )
    {
        switch( $type )
        {
            case 'event':
                // create a voting repository with EventVote table
                return new VotingRepository( new EventVoteTable() );
            case 'comment':
                // create a voting repository with CommentVote table
                return new VotingRepository( new CommentVoteTable() );
            case 'user':
                // create a voting repository with UserVote table
                return new VotingRepository( new UserVoteTable() );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,从域对象(例如,在这种情况下评论)中将它们全部捆绑在一起,我会看起来像这样:

class Comment implements Voteable
{
    public function construct()
    {
        $this->_repository = VotingRepositoryFactory::createVotingRepository( 'comment' );
    }

    public function vote( User $user, $value )
    {
        $this->_repository->castVote( $this, $user, $value );
    }
}
Run Code Online (Sandbox Code Playgroud)

这有意义吗?

stm*_*max 4

是的,存储库和工厂都有意义。

关于工厂的一些评论:

我会删除switch ($type)并为每种类型的 Votable 对象创建方法。所以而不是

VotingRepositoryFactory::createVotingRepository( 'comment' );

我更喜欢

VotingRepositoryFactory::createCommentVotingRepository();

原因是很容易忘记向开关添加新的情况,而(我不确定 php,但是)编译语言会告诉您何时缺少被调用的方法。记住可以将哪些字符串作为 $type 发送到工厂方法中也很困难,而大多数智能 IDE 会告诉您类/对象上存在哪些方法。

另一个想法是添加一个可以像VotingRepositoryFactory::Instance->createCommentVotingRepository();. “实例”可以是 DatabaseVotingRepositoryFactory 或 FakeVotingRepositoryFactory(用于单元测试)或 VotingRepositoryFactory 的任何其他实现。这样,如果您想编写单元测试或切换到其他存储系统,您可以轻松替换 VotingRepositoryFactory 的实现。

只是一些想法..