Skip to content

Commit 9c648cb

Browse files
committed
Update README.md
1 parent e6cca86 commit 9c648cb

File tree

1 file changed

+43
-25
lines changed

1 file changed

+43
-25
lines changed

specification/README.md

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,46 @@ tags:
99
---
1010

1111
## Also known as
12+
1213
Filter, Criteria
1314

1415
## Intent
15-
Specification pattern separates the statement of how to match a
16-
candidate, from the candidate object that it is matched against. As well as its
17-
usefulness in selection, it is also valuable for validation and for building to
18-
order.
16+
17+
Specification pattern separates the statement of how to match a candidate, from the candidate object
18+
that it is matched against. As well as its usefulness in selection, it is also valuable for
19+
validation and for building to order.
1920

2021
## Explanation
2122

2223
Real world example
2324

24-
> There is a pool of different creatures and we often need to select some subset of them.
25-
> We can write our search specification such as "creatures that can fly", "creatures heavier than 500 kilograms", or as a combination of other search specifications, and then give it to the party that will perform the filtering.
25+
> There is a pool of different creatures and we often need to select some subset of them. We can
26+
> write our search specification such as "creatures that can fly", "creatures heavier than 500
27+
> kilograms", or as a combination of other search specifications, and then give it to the party that
28+
> will perform the filtering.
2629
2730
In Plain Words
2831

29-
> Specification pattern allows us to separate the search criteria from the object that performs the search.
32+
> Specification pattern allows us to separate the search criteria from the object that performs the
33+
> search.
3034
3135
Wikipedia says
3236

33-
> In computer programming, the specification pattern is a particular software design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic.
37+
> In computer programming, the specification pattern is a particular software design pattern,
38+
> whereby business rules can be recombined by chaining the business rules together using boolean
39+
> logic.
3440
3541
**Programmatic Example**
3642

37-
If we look at our creature pool example from above, we have a set of creatures with certain properties.
38-
Those properties can be part of a pre-defined, limited set (represented here by the enums Size, Movement and Color); but they can also be continuous values (e.g. the mass of a Creature).
39-
In this case, it is more appropriate to use what we call "parameterized specification", where the property value can be given as an argument when the Creature is instantiated, allowing for more flexibility.
40-
A third option is to combine pre-defined and/or parameterized properties using boolean logic, allowing for near-endless selection possibilities (this is called "composite specification", see below).
41-
The pros and cons of each approach are detailed in the table at the end of this document.
43+
If we look at our creature pool example from above, we have a set of creatures with certain
44+
properties. Those properties can be part of a pre-defined, limited set (represented here by the
45+
enums Size, Movement and Color); but they can also be continuous values (e.g. the mass of a
46+
Creature). In this case, it is more appropriate to use what we call "parameterized specification",
47+
where the property value can be given as an argument when the Creature is instantiated, allowing for
48+
more flexibility. A third option is to combine pre-defined and/or parameterized properties using
49+
boolean logic, allowing for near-endless selection possibilities (this is called "composite
50+
specification", see below). The pros and cons of each approach are detailed in the table at the end
51+
of this document.
4252

4353
```java
4454
public interface Creature {
@@ -50,7 +60,7 @@ public interface Creature {
5060
}
5161
```
5262

53-
And ``Dragon`` implementation looks like this.
63+
And `Dragon` implementation looks like this.
5464

5565
```java
5666
public class Dragon extends AbstractCreature {
@@ -61,7 +71,8 @@ public class Dragon extends AbstractCreature {
6171
}
6272
```
6373

64-
Now that we want to select some subset of them, we use selectors. To select creatures that fly, we should use ``MovementSelector``.
74+
Now that we want to select some subset of them, we use selectors. To select creatures that fly, we
75+
should use `MovementSelector`.
6576

6677
```java
6778
public class MovementSelector extends AbstractSelector<Creature> {
@@ -79,7 +90,8 @@ public class MovementSelector extends AbstractSelector<Creature> {
7990
}
8091
```
8192

82-
On the other hand, when selecting creatures heavier than a chosen amount, we use ``MassGreaterThanSelector``.
93+
On the other hand, when selecting creatures heavier than a chosen amount, we use
94+
`MassGreaterThanSelector`.
8395

8496
```java
8597
public class MassGreaterThanSelector extends AbstractSelector<Creature> {
@@ -111,7 +123,8 @@ But we could also use our parameterized selector like this:
111123
.collect(Collectors.toList());
112124
```
113125

114-
Our third option is to combine multiple selectors together. Performing a search for special creatures (defined as red, flying, and not small) could be done as follows:
126+
Our third option is to combine multiple selectors together. Performing a search for special
127+
creatures (defined as red, flying, and not small) could be done as follows:
115128

116129
```java
117130
var specialCreaturesSelector =
@@ -123,8 +136,9 @@ Our third option is to combine multiple selectors together. Performing a search
123136

124137
**More on Composite Specification**
125138

126-
In Composite Specification, we will create custom instances of ``AbstractSelector`` by combining other selectors (called "leaves") using the three basic logical operators.
127-
These are implemented in ``ConjunctionSelector``, ``DisjunctionSelector`` and ``NegationSelector``.
139+
In Composite Specification, we will create custom instances of `AbstractSelector` by combining
140+
other selectors (called "leaves") using the three basic logical operators. These are implemented in
141+
`ConjunctionSelector`, `DisjunctionSelector` and `NegationSelector`.
128142

129143
```java
130144
public abstract class AbstractSelector<T> implements Predicate<T> {
@@ -163,12 +177,14 @@ public class ConjunctionSelector<T> extends AbstractSelector<T> {
163177
}
164178
```
165179

166-
All that is left to do is now to create leaf selectors (be it hard-coded or parameterized ones) that are as generic as possible,
167-
and we will be able to instantiate the ``AbstractSelector`` class by combining any amount of selectors, as exemplified above.
168-
We should be careful though, as it is easy to make a mistake when combining many logical operators; in particular, we should pay attention to the priority of the operations.\
169-
In general, Composite Specification is a great way to write more reusable code, as there is no need to create a Selector class for each filtering operation.
170-
Instead, we just create an instance of ``AbstractSelector`` "on the spot", using tour generic "leaf" selectors and some basic boolean logic.
171-
180+
All that is left to do is now to create leaf selectors (be it hard-coded or parameterized ones) that
181+
are as generic as possible, and we will be able to instantiate the ``AbstractSelector`` class by
182+
combining any amount of selectors, as exemplified above. We should be careful though, as it is easy
183+
to make a mistake when combining many logical operators; in particular, we should pay attention to
184+
the priority of the operations. In general, Composite Specification is a great way to write more
185+
reusable code, as there is no need to create a Selector class for each filtering operation. Instead,
186+
we just create an instance of ``AbstractSelector`` "on the spot", using tour generic "leaf"
187+
selectors and some basic boolean logic.
172188

173189
**Comparison of the different approaches**
174190

@@ -181,9 +197,11 @@ Instead, we just create an instance of ``AbstractSelector`` "on the spot", using
181197
| | | + Supports logical operations | - You still need to create the base classes used as leaves |
182198

183199
## Class diagram
200+
184201
![alt text](./etc/specification.png "Specification")
185202

186203
## Applicability
204+
187205
Use the Specification pattern when
188206

189207
* You need to select a subset of objects based on some criteria, and to refresh the selection at various times.

0 commit comments

Comments
 (0)