状态模式实现发布电影后的各种状态下的编辑删除更新等

实现功能:

用户发布的一部电影在审核时,和审核通过后,对应的操作各不相同.

一.定义两个异常

/**
 * 定义一个权限拒绝异常
 * Class PermissionDeniedException
 */
class PermissionDeniedException extends Exception
{
    protected $message    = '权限拒绝';
    protected $code       = 2000;

    public function __construct()
    {
        parent::__construct($this->message, $this->code);
    }
}

  

/**
 * 数据未发现异常
 * Class NotFoundMovieException
 */
class NotFoundMovieException extends Exception
{
    protected $message    = '数据未发现';
    protected $code       = 404;

    public function __construct()
    {
        parent::__construct($this->message, $this->code);
    }
}

  

二.定义一个数据类(模拟从数据库获取数据)

/**
 * 电影类
 * Class DbMovie
 */
class DbMovie
{
    const MOVIES = [
        ['id' => 1, 'uid' => 10, 'title' => '铁胆雄心', 'state' => 2]
    ];

    /**
     * 模拟查找数据
     * @param $id
     * @return bool|mixed
     */
    public function find($id)
    {
        foreach (self::MOVIES as $movie) {
            if ($movie['id'] === $id) {
                return $movie;
            }
        }
        return false;
    }
}

  

三.定义状态接口

/**
 * 状态接口
 * Interface MovieStateInterface
 */
interface MovieStateInterface
{
    public function show($requestUid);
    public function delete($requestUid);
    public function edit($requestUid);
    public function update($requestUid);
}

  

四.定义一个虚拟电影基类

/**
 * Class MovieState
 */
abstract class MovieState
{
    protected $movie;

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

  

五.定义等待审核状态的电影

/**
 * 等待审核中的电影
 * Class ReviewMovie
 */
class ReviewMovie extends MovieState implements MovieStateInterface
{
    // 允许发布者自己可以查看
    public function show($requestUid)
    {
        if ($requestUid === $this->movie['uid']) {
            return $this->movie;
        } else {
            throw new PermissionDeniedException();
        }
    }

    public function delete($requestUid)
    {
        throw new PermissionDeniedException();
    }

    public function edit($requestUid)
    {
        throw new PermissionDeniedException();
    }

    public function update($requestUid)
    {
        throw new PermissionDeniedException();
    }
}

  

五.定义审核通过后的电影

/**
 * 审核通过的电影: 允许发布者查看,删除,编辑和更新,其余人只可查看
 * Class NomarlMovie
 */
class NormalMovie extends MovieState implements MovieStateInterface
{
    public function show($requestUid)
    {
        return $this->movie;
    }

    public function delete($requestUid)
    {
        if ($requestUid === $this->movie['uid']) {
            echo '删除成功<br/>';
        } else {
            throw new PermissionDeniedException();
        }
    }

    public function edit($requestUid)
    {
        if ($requestUid === $this->movie['uid']) {
            echo '可以编辑<br/>';
        } else {
            throw new PermissionDeniedException();
        }
    }

    public function update($requestUid)
    {
        if ($requestUid === $this->movie['uid']) {
            echo '更新成功<br/>';
            return true;
        } else {
            throw new PermissionDeniedException();
        }
    }
}

  

六.状态上下文类

class Context
{
    // 所有状态码对应的状态类
    const MOVIE_STATES = [
        1 => ReviewMovie::class,
        2 => NormalMovie::class,
    ];

    // 状态码
    private $state;
    // 电影
    private $movie;
    // 状态对象
    private $movieState;

    public function __construct($movieId, $uid)
    {
        $this->uid = $uid;

        $movieModel = new DbMovie();
        $this->movie      = $movieModel->find($movieId);
        if ($this->movie === false) {
            throw new NotFoundMovieException();
        }

        // 状态码的修改根据保存在数据库中电影的状态来改变
        $this->state = $this->movie['state'];
        // 切换状态码
        $this->setMovieState();
    }

    protected function setMovieState()
    {
        $currentStateClass          = self::MOVIE_STATES[$this->state];
        $this->movieState           = new $currentStateClass($this->movie);
    }

    public function show()
    {
        return $this->movieState->show($this->uid);
    }

    public function delete()
    {
        return $this->movieState->delete($this->uid);
    }

    public function edit()
    {
        return $this->movieState->edit($this->uid);
    }

    public function update()
    {
        return $this->movieState->update($this->uid);
    }
}

  

七.调用

try{
    $client = new Context($movieId = 1, $uid = 10);
    var_dump($client->show());
    var_dump($client->update());
} catch (NotFoundMovieException $e) {
    echo $e->getMessage();
} catch (PermissionDeniedException $e) {
    echo $e->getMessage();
} catch (Exception $e) {
    echo $e->getMessage();
}

  

原文地址:https://www.cnblogs.com/itfenqing/p/8733412.html