命令查询职责分离模式 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 网站上。

上一篇 下一篇
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
发起讨论 查看所有版本


暂无话题~