Adding parameterized specification (Issue#1055) (#1088)

* Resolution proposition to Issue#1055 (UML diagram left to do)

* Deciding not to modify the UML diagram for now
This commit is contained in:
Martin Vandenbussche
2019-11-16 13:24:46 +01:00
committed by Ilkka Seppälä
parent cc571f4149
commit df8a4e3b47
17 changed files with 328 additions and 30 deletions

View File

@ -31,7 +31,7 @@ Use the Specification pattern when
Real world example
> There is a pool of different creatures and we often need to select some subset of them. We can write our search specification such as "creatures that can fly" and give it to the party that will perform the filtering.
> There is a pool of different creatures and we often need to select some subset of them. We can write our search specification such as "creatures that can fly" or "creatures heavier than 500 kilograms" and give it to the party that will perform the filtering.
In Plain Words
@ -43,7 +43,8 @@ Wikipedia says
**Programmatic Example**
If we look at our creature pool example from above, we have a set of creatures with certain properties.
If we look at our creature pool example from above, we have a set of creatures with certain properties.\
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 discrete (e.g. the mass of a Creature). 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 created, allowing for more flexibility.
```java
public interface Creature {
@ -51,6 +52,7 @@ public interface Creature {
Size getSize();
Movement getMovement();
Color getColor();
Mass getMass();
}
```
@ -60,7 +62,7 @@ And dragon implementation looks like this.
public class Dragon extends AbstractCreature {
public Dragon() {
super("Dragon", Size.LARGE, Movement.FLYING, Color.RED);
super("Dragon", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0));
}
}
```
@ -83,6 +85,24 @@ public class MovementSelector implements Predicate<Creature> {
}
```
On the other hand, we selecting creatures heavier than a chosen amount, we use MassGreaterThanSelector.
```java
public class MassGreaterThanSelector implements Predicate<Creature> {
private final Mass mass;
public MassGreaterThanSelector(double mass) {
this.mass = new Mass(mass);
}
@Override
public boolean test(Creature t) {
return t.getMass().greaterThan(mass);
}
}
```
With these building blocks in place, we can perform a search for red and flying creatures like this.
```java
@ -90,6 +110,13 @@ With these building blocks in place, we can perform a search for red and flying
.filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))).collect(Collectors.toList());
```
But we could also use our paramterized selector like this.
```java
List<Creature> heavyCreatures = creatures.stream()
.filter(new MassGreaterThanSelector(500.0).collect(Collectors.toList());
```
## Related patterns
* Repository