1、模式定义
规格模式是组合模式的一种扩展,在框架性开发中使用较多(项目级开发很少使用),这里做一个简单的介绍。
规格模式(Specification)可以认为是组合模式的一种扩展。有时项目中某些条件决定了业务逻辑,这些条件就可以抽离出来以某种关系(与、或、非)进行组合,从而灵活地对业务逻辑进行定制。另外,在查询、过滤等应用场合中,通过预定义多个条件,然后使用这些条件的组合来处理查询或过滤,而不是使用逻辑判断语句来处理,可以简化整个实现逻辑。
这里的每个条件就是一个规格,多个规格/条件通过串联的方式以某种逻辑关系形成一个组合式的规格。
2、UML类图
3、示例代码
Item.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<?php
namespace DesignPatterns\Behavioral\Specification;
class Item
{
protected $price ;
/**
* An item must have a price
*
* @param int $price
*/
public function __construct( $price )
{
$this ->price = $price ;
}
/**
* Get the items price
*
* @return int
*/
public function getPrice()
{
return $this ->price;
}
}
|
SpecificationInterface.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<?php
namespace DesignPatterns\Behavioral\Specification;
/**
* 规格接口
*/
interface SpecificationInterface
{
/**
* 判断对象是否满足规格
*
* @param Item $item
*
* @return bool
*/
public function isSatisfiedBy(Item $item );
/**
* 创建一个逻辑与规格(AND)
*
* @param SpecificationInterface $spec
*/
public function plus(SpecificationInterface $spec );
/**
* 创建一个逻辑或规格(OR)
*
* @param SpecificationInterface $spec
*/
public function either(SpecificationInterface $spec );
/**
* 创建一个逻辑非规格(NOT)
*/
public function not();
}
|
AbstractSpecification.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
<?php
namespace DesignPatterns\Behavioral\Specification;
/**
* 规格抽象类
*/
abstract class AbstractSpecification implements SpecificationInterface
{
/**
* 检查给定Item是否满足所有规则
*
* @param Item $item
*
* @return bool
*/
abstract public function isSatisfiedBy(Item $item );
/**
* 创建一个新的逻辑与规格(AND)
*
* @param SpecificationInterface $spec
*
* @return SpecificationInterface
*/
public function plus(SpecificationInterface $spec )
{
return new Plus( $this , $spec );
}
/**
* 创建一个新的逻辑或组合规格(OR)
*
* @param SpecificationInterface $spec
*
* @return SpecificationInterface
*/
public function either(SpecificationInterface $spec )
{
return new Either( $this , $spec );
}
/**
* 创建一个新的逻辑非规格(NOT)
*
* @return SpecificationInterface
*/
public function not()
{
return new Not( $this );
}
}
|
Plus.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<?php
namespace DesignPatterns\Behavioral\Specification;
/**
* 逻辑与规格(AND)
*/
class Plus extends AbstractSpecification
{
protected $left ;
protected $right ;
/**
* 在构造函数中传入两种规格
*
* @param SpecificationInterface $left
* @param SpecificationInterface $right
*/
public function __construct(SpecificationInterface $left , SpecificationInterface $right )
{
$this ->left = $left ;
$this ->right = $right ;
}
/**
* 返回两种规格的逻辑与评估
*
* @param Item $item
*
* @return bool
*/
public function isSatisfiedBy(Item $item )
{
return $this ->left->isSatisfiedBy( $item ) && $this ->right->isSatisfiedBy( $item );
}
}
|
Either.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<?php
namespace DesignPatterns\Behavioral\Specification;
/**
* 逻辑或规格
*/
class Either extends AbstractSpecification
{
protected $left ;
protected $right ;
/**
* 两种规格的组合
*
* @param SpecificationInterface $left
* @param SpecificationInterface $right
*/
public function __construct(SpecificationInterface $left , SpecificationInterface $right )
{
$this ->left = $left ;
$this ->right = $right ;
}
/**
* 返回两种规格的逻辑或评估
*
* @param Item $item
*
* @return bool
*/
public function isSatisfiedBy(Item $item )
{
return $this ->left->isSatisfiedBy( $item ) || $this ->right->isSatisfiedBy( $item );
}
}
|
Not.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<?php
namespace DesignPatterns\Behavioral\Specification;
/**
* 逻辑非规格
*/
class Not extends AbstractSpecification
{
protected $spec ;
/**
* 在构造函数中传入指定规格
*
* @param SpecificationInterface $spec
*/
public function __construct(SpecificationInterface $spec )
{
$this ->spec = $spec ;
}
/**
* 返回规格的相反结果
*
* @param Item $item
*
* @return bool
*/
public function isSatisfiedBy(Item $item )
{
return ! $this ->spec->isSatisfiedBy( $item );
}
}
|
PriceSpecification.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
<?php
namespace DesignPatterns\Behavioral\Specification;
/**
* 判断给定Item的价格是否介于最小值和最大值之间的规格
*/
class PriceSpecification extends AbstractSpecification
{
protected $maxPrice ;
protected $minPrice ;
/**
* 设置最大值
*
* @param int $maxPrice
*/
public function setMaxPrice( $maxPrice )
{
$this ->maxPrice = $maxPrice ;
}
/**
* 设置最小值
*
* @param int $minPrice
*/
public function setMinPrice( $minPrice )
{
$this ->minPrice = $minPrice ;
}
/**
* 判断给定Item的定价是否在最小值和最大值之间
*
* @param Item $item
*
* @return bool
*/
public function isSatisfiedBy(Item $item )
{
if (! empty ( $this ->maxPrice) && $item ->getPrice() > $this ->maxPrice) {
return false;
}
if (! empty ( $this ->minPrice) && $item ->getPrice() < $this ->minPrice) {
return false;
}
return true;
}
}
|
4、测试代码
Tests/SpecificationTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
<?php
namespace DesignPatterns\Behavioral\Specification\Tests;
use DesignPatterns\Behavioral\Specification\PriceSpecification;
use DesignPatterns\Behavioral\Specification\Item;
/**
* SpecificationTest 用于测试规格模式
*/
{
public function testSimpleSpecification()
{
$item = new Item(100);
$spec = new PriceSpecification();
$this ->assertTrue( $spec ->isSatisfiedBy( $item ));
$spec ->setMaxPrice(50);
$this ->assertFalse( $spec ->isSatisfiedBy( $item ));
$spec ->setMaxPrice(150);
$this ->assertTrue( $spec ->isSatisfiedBy( $item ));
$spec ->setMinPrice(101);
$this ->assertFalse( $spec ->isSatisfiedBy( $item ));
$spec ->setMinPrice(100);
$this ->assertTrue( $spec ->isSatisfiedBy( $item ));
}
public function testNotSpecification()
{
$item = new Item(100);
$spec = new PriceSpecification();
$not = $spec ->not();
$this ->assertFalse( $not ->isSatisfiedBy( $item ));
$spec ->setMaxPrice(50);
$this ->assertTrue( $not ->isSatisfiedBy( $item ));
$spec ->setMaxPrice(150);
$this ->assertFalse( $not ->isSatisfiedBy( $item ));
$spec ->setMinPrice(101);
$this ->assertTrue( $not ->isSatisfiedBy( $item ));
$spec ->setMinPrice(100);
$this ->assertFalse( $not ->isSatisfiedBy( $item ));
}
public function testPlusSpecification()
{
$spec1 = new PriceSpecification();
$spec2 = new PriceSpecification();
$plus = $spec1 ->plus( $spec2 );
$item = new Item(100);
$this ->assertTrue( $plus ->isSatisfiedBy( $item ));
$spec1 ->setMaxPrice(150);
$spec2 ->setMinPrice(50);
$this ->assertTrue( $plus ->isSatisfiedBy( $item ));
$spec1 ->setMaxPrice(150);
$spec2 ->setMinPrice(101);
$this ->assertFalse( $plus ->isSatisfiedBy( $item ));
$spec1 ->setMaxPrice(99);
$spec2 ->setMinPrice(50);
$this ->assertFalse( $plus ->isSatisfiedBy( $item ));
}
public function testEitherSpecification()
{
$spec1 = new PriceSpecification();
$spec2 = new PriceSpecification();
$either = $spec1 ->either( $spec2 );
$item = new Item(100);
$this ->assertTrue( $either ->isSatisfiedBy( $item ));
$spec1 ->setMaxPrice(150);
$spec2 ->setMaxPrice(150);
$this ->assertTrue( $either ->isSatisfiedBy( $item ));
$spec1 ->setMaxPrice(150);
$spec2 ->setMaxPrice(0);
$this ->assertTrue( $either ->isSatisfiedBy( $item ));
$spec1 ->setMaxPrice(0);
$spec2 ->setMaxPrice(150);
$this ->assertTrue( $either ->isSatisfiedBy( $item ));
$spec1 ->setMaxPrice(99);
$spec2 ->setMaxPrice(99);
$this ->assertFalse( $either ->isSatisfiedBy( $item ));
}
}
|
以上内容是服务器之家小编给大家分享的PHP 设计模式系列之 specification规格模式,希望本文分享能够帮助大家。