2016-02-11 145 views
1

我正嘗試使用策略模式來解決設計問題。這是一個大學系統。有一個用戶,用戶可以是學生,教授或管理員。所以,我有這樣使用策略模式無法避免切換條件

<?php 

namespace Domain\Model\User; 

class User 
{ 
    private $user_type; 

    public function __construct(UserType $user_type) 
    { 
     $this->user_type = $user_type; 
    } 

    public function hasAccess() 
    { 
     $this->type()->hasAccess(); 
    } 
    // others methods 
} 

UserTypeUser實體是一個接口,每一個用戶類型實現它。像StudentType:我不想與Strategy Pattern創建ACL

<?php 

namespace Domain\Model\User; 

class StudentType implements UserType 
{ 
    public function hasAccess() 
    { 
     // checks if has access 
    } 
} 

通知,我已經在使用一個。這裏的要點是每種類型的用戶都有一個訪問環境的正確方法,所以我必須做一些檢查。

所以問題是User實體的方法type()。我知道在建模實體時我不必考慮數據庫,但所有這些類型,用戶,學生都存儲在關係數據庫中,我無法避免這種情況。所以,我使用Doctrine作爲持久性。

當我從數據庫中檢索User,學說不使用我User的構造,所以$user_type屬性將只有一個號碼。然後,爲了保證$user_type屬性將始終是實現UserType接口的類,我只好用type()方法做這樣的事情

// method inside User class 
public function type() 
{ 
    if (!$this->user_type instanceof UserType) { 
     switch ($this->user_type) { 
      case 1: 
       $this->user_type = new StudentType; 
       break; 
      // some others ugly conditions for each type 
     } 
    } 
    return $this->user_type; 
} 

有沒有辦法避免使用這些條件語句?或者我是否以錯誤的方式思考戰略模式?

+0

也許看看Doctrine的繼承:http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#inheritance-mapping。但我懷疑基於角色的方法可能是您所需要的。 – Cerad

回答

0

您可以通過活動登錄Doctrine的EventManager參見this。此事件將允許您在從數據庫加載完成後處理每個實體。

就我個人而言,我不太喜歡使用EventManager太多,我也不喜歡實體「太聰明」。我認爲一個User實體本身的實例不應該能夠決定它是否可以訪問某個地方。一些業務對象/服務應負責決定。此服務將有hasAccess方法,其中User實體和適當的答案。 (具有您的StudentType,TeacherType等邏輯)然後,該服務將能夠處理user_type或角色,無論它是一個整數還是字符串。