doyrte8419 2016-02-11 18:43
浏览 33

使用策略模式无法避免切换条件

I'm trying to use the strategy pattern to solve a design issue. It's a college system. There is an User, and the user can be either a Student, a Professor or an Administrator. So, I have an User entity like this

<?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 
}

The UserType is an Interface, that each user type implements it. Like the StudentType:

<?php

namespace Domain\Model\User;

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

Notice that I don't want to create an ACL with Strategy Pattern, I'm already using one. The point here is that each type of user has a proper way to access an environment, so I have to do some checks.

So the question is the method type() of the User entity. I know that I don't have to think about database when modeling my entities, but all these types, users, students are stored in a relational database, and I can't avoid this. So, I'm using Doctrine for persistence.

When I retrieve an User from the database, Doctrine don't uses the constructor of my User, so the $user_type attribute will be only a number. Then, to guarantee that $user_type property will always be a class that implements the UserType interface, I had to use the type() method to do something like this

// 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;
}

Is there a way to avoid using these conditionals? Or am I thinking in the wrong way about Strategy Pattern?

  • 写回答

1条回答 默认 最新

  • douxianglu4370 2016-02-15 13:17
    关注

    You can hook to postLoad event in Doctrine's EventManager see this. This event will let you process each entity after is has been loaded from the DB.

    Personally I don't like using EventManager too much and I don't like entities being "too clever" either. I think an instance of User entity itself should not be able to decide if it has access somewhere or not. Some business object/service should be in charge of deciding that. This service would have hasAccess method that takes your User entity and answers appropriately. (Having logic of your StudentType, TeacherType etc.) Then the service would be able to handle user_type or role, no matter if it is an integer or string.

    评论

报告相同问题?

悬赏问题

  • ¥50 我撰写的python爬虫爬不了 要爬的网址有反爬机制
  • ¥15 Centos / PETSc / PETGEM
  • ¥15 centos7.9 IPv6端口telnet和端口监控问题
  • ¥120 计算机网络的新校区组网设计
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 海浪数据 南海地区海况数据,波浪数据
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法