规范设计模式

规范设计模式非常强大。在这里,我将尝试对其进行高层次的概述,但还有很多值得探索的地方;如果您有兴趣了解更多信息,我强烈推荐 Eric Evans 和 Martin Fowler 撰写的论文《规格》。

此设计模式用于编写说明有关对象的某些内容的业务规则。它们告诉我们一个对象是否满足某些业务标准。

我们可以通过以下方式使用它们:

  • 对对象做出断言以进行验证(validation)

  • 从给定集合中获取选定(selection)的对象

  • 指定如何通过按顺序构建来创建对象

在此示例中,我们将构建规范来查询

让我们采用以下对象:

<?php

$workers = array();

$workers['A'] = new StdClass();
$workers['A']->title = "Developer";
$workers['A']->department = "Engineering";
$workers['A']->salary = 50000;

$workers['B'] = new StdClass();
$workers['B']->title = "Data Analyst";
$workers['B']->department = "Engineering";
$workers['B']->salary = 30000;

$workers['C'] = new StdClass();
$workers['C']->title = "Personal Assistant";
$workers['C']->department = "CEO";
$workers['C']->salary = 25000;

The workers array will look like this if we var_dump it:
array(3) {
["A"]=>
    object(stdClass)#1 (3) {
        ["title"]=>
        string(9) "Developer"
        ["department"]=>
        string(11) "Engineering"
        ["salary"]=>
        int(50000)
    }

["B"]=>
    object(stdClass)#2 (3) {
        ["title"]=>
        string(12) "Data Analyst"
        ["department"]=>
        string(11) "Engineering"
        ["salary"]=>
        int(30000)
    }

["C"]=>
    object(stdClass)#3 (3) {
        ["title"]=>
        string(18) "Personal Assistant"
        ["department"]=>
        string(3) "CEO"
        ["salary"]=>
        int(25000)
    }
}

让我们从 EmployeeSpecification 接口开始;这是我们所有规范都需要实现的接口。请务必将 StdClass 替换为您要处理的对象类型(例如,雇员或您实例化对象的类名)。

代码如下:

Unresolved include directive in modules/ROOT/pages/ch05/ch5-08.adoc - include::example$Chapter 5/Specification/EmployeeSpecification.php[]

是时候编写一个名为 EmployeeIsEngineer 的实现了:

Unresolved include directive in modules/ROOT/pages/ch05/ch5-08.adoc - include::example$Chapter 5/Specification/EmployeeIsEngineer.php[]

然后我们可以迭代我们的工作人员来检查哪些工作人员符合我们概述的标准:

$isEngineer = new EmployeeIsEngineer();

foreach ($workers as $id => $worker) {
    if ($isEngineer->isSatisfiedBy($worker)) {
        var_dump($id);
    }
}

让我们将所有这些放在我们的 index.php 文件中:

Unresolved include directive in modules/ROOT/pages/ch05/ch5-08.adoc - include::example$Chapter 5/Specification/index.php[]

这是该脚本的输出:

image 2023 10 31 11 34 21 771

复合规范允许您组合规范。通过使用 ANDNOTORNOR 操作符,您可以在不同的规范类中建立各自的功能。

同样,您也可以使用规范来获取对象。

随着研究的深入,这些代码会变得越来越复杂,但大意还是可以理解的。事实上,我在本节开头提到的埃里克-埃文斯(Eric Evans)和马丁-福勒(Martin Fowler)的论文中还提到了一些更为复杂的安排。

无论如何,这种设计模式从根本上允许我们封装业务逻辑,以说明对象的一些情况。这是一种非常强大的设计模式,我强烈建议大家对它进行更深入的研究。