2016-02-11 67 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或角色,无论它是一个整数还是字符串。