命令查询职责分离模式 Command and Query Responsibility Segregation (CQRS) Pattern

未匹配的标注

描述

    把应用拆分成查询和更新两部分。这种模式可以最大限度地提高性能,可扩展性和安全性。

背景和问题

    在传统的数据管理系统中,数据存储可能会同时执行读和写操作,这意味着有读写之间会有资源的争夺,着对性能是会有负面的影响的。

解决方案

    程序中的读和写操作分开。读就是查询(Query),写就是更新,也称为命令(Command)。

注意事项

    把数据分拆成读和写操作可以提高系统的性能和安全性,但是数据同步存在延迟了。

何时使用

  1. 业务单一,有大量读写操作的程序。
  2. 想通过读写分离提高业务性能。

结构中包含的角色

  1. CommandStorage 抽象命令仓库
  2. QueryStorage 抽象查询仓库
  3. Mysql 具体仓库
  4. CommandMysql 具体命令仓库
  5. QueryMysql 具体查询仓库
  6. QueryService 查询服务
  7. CommandService 命令服务

可用到的设计模式思维

    仓库按照功能分成两部分,一部分是查询,另外一部分是更新(命令)。查询仓库可以看成一个代理,限制这个代理只负责仓库的查询部分,而命令仓库就是更新部分,它们使用相同数据的仓库(可能使用同一个仓库,可能是两个数据一摸一样的仓库)。

最小可表达代码

// 抽象命令仓库
interface CommandStorage
{
    public function updateById($id, array $attribute);
}

// 抽象查询仓库
interface QueryStorage
{
    public function all();
}

// 具体仓库
class Mysql implements CommandStorage, QueryStorage
{
    protected $students = [
        ['id' => 1, 'name' => '张三', 'age' => 18],
    ];

    public function updateById($id, array $attribute)
    {
        foreach ($this->students as &$student) {
            if ($id == $student['id']) {
                $student = $attribute + $student;
            }
        }

        unset($student);

        return true;
    }

    public function all()
    {
        return $this->students;
    }
}

// 具体命令仓库
class CommandMysql implements CommandStorage
{
    protected $commandStorage;

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

    public function updateById($id, array $attribute)
    {
        return $this->commandStorage->updateById($id, $attribute);
    }
}

// 具体查询仓库
class QueryMysql implements QueryStorage
{
    protected $queryStorage;

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

    public function all()
    {
        return $this->queryStorage->all();
    }
}

// 查询服务
class QueryService
{
    protected $queryStorage;

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

    public function all()
    {
        return $this->queryStorage->all();
    }
}

// 命令服务
class CommandService
{
    protected $commandStorage;

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

    public function update()
    {
        return $this->commandStorage->updateById(1, ['age' => 11]);
    }
}

$mysql = new Mysql;
$commandService = new CommandService(new CommandMysql($mysql));
$commandService->update();
$queryService = new QueryService(new QueryMysql($mysql));
$data = $queryService->all();
var_dump($data);

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
发起讨论 只看当前版本


暂无话题~