2010-02-25 86 views
7

我想创建一个投票系统,在多个领域对象可以进行表决:这是一个很好的工厂候选人吗?

  • 日历事件
  • 评论
  • 用户

所以我想我会创建一个Voteable接口,用于以下项目:

interface Voteable 
{ 
    public function vote(User $user, $value); 
} 

我认为这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(); 

    } 
} 

目前,该库将是一个数据库。这个数据库将对每种类型的投票链接表:

  • eventVote
  • commentVote
  • userVote

所以,这基本上意味着,每个域对象需要另一个表来投的票。这会成为工厂的一个很好的候选人吗? A 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()); 
     } 
    } 
} 

然后,域对象中尝试所有这些,从(在这种情况下,例如评论),我会是这个样子:

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

    public function vote(User $user, $value) 
    { 
     $this->_repository->castVote($this, $user, $value); 
    } 
} 

这是否合理?

+0

只要记住不要太过分的设计模式。设计模式在有效且审慎地使用时会创建优雅且易于维护的代码。然而,你也想避免建造10英尺脚手架的陷阱,只是为了把你的钟挂在墙上。这就是说,我喜欢在太多的脚手架上犯错。 ;-) – 2010-02-25 21:26:56

+0

@Jeff:我听到你在说什么。该网站将是一个相当雄心勃勃的项目(至少对我而言)。所以我希望它可以从git go尽可能保持。 – 2010-02-25 21:39:24

回答

4

是的版本库和工厂都有意义。

有关工厂几点意见:

我会删除switch ($type),并为每种类型的可投票对象的方法。所以不是

VotingRepositoryFactory::createVotingRepository('comment');

我宁愿

VotingRepositoryFactory::createCommentVotingRepository();

的原因是很容易忘记一个新的情况下添加到交换机上,同时(我不知道PHP,但)编译语言会告诉你何时缺少一个被调用的方法。还要记住你可以将哪些字符串发送到工厂方法中,因为$ type很难,而大多数智能IDE会告诉你类/对象上存在哪些方法。

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

只是一些想法..

+0

+1这是一些很棒的附加信息。谢谢。所以,让我看看我是否明白了这一点:换句话说,你说'getInstance()'也会像工厂一样?例如,基于某个配置返回另一个工厂?这是什么被称为抽象工厂的任何机会? – 2010-02-25 21:22:36

+0

是的,getInstance()返回的对象将是一个抽象工厂。你可以使用某种配置文件来告诉它应该创建什么类型的工厂。有时我甚至只是硬编码(_instance = new ...)。一旦你必须(一行代码),它仍然很容易替换。一旦越来越多的单身人士开始在你的应用程序中弹出,你可能还想看看“ServiceLocator”模式或某种IoC容器......这样你可以配置所有的单身人士(以及更多)一个中心的地方。 – stmax 2010-02-25 21:39:28

2

是的,它的确如此。

:]

+0

什么?!没有,如果是,还是但是......?毕竟,我真的开始了解这个问题吗?哇噢! :-D – 2010-02-25 20:31:26

+0

嗯..对不起,但你已经用完美的答案回答了你的问题 – streetparade 2010-02-25 20:34:11

+0

那么,对你们俩来说:谢谢你们俩的安慰。 – 2010-02-25 20:49:19

相关问题