2010-02-25 22 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

相關問題