Update README.md
This commit is contained in:
parent
0cba307844
commit
015b418114
@ -11,27 +11,33 @@ tags:
|
|||||||
---
|
---
|
||||||
|
|
||||||
## Name / classification
|
## Name / classification
|
||||||
|
|
||||||
Filterer
|
Filterer
|
||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
The intent of this design pattern is to introduce a functional interface that will add a functionality for container-like objects to easily return filtered versions of themselves.
|
|
||||||
|
The intent of this design pattern is to introduce a functional interface that will add a
|
||||||
|
functionality for container-like objects to easily return filtered versions of themselves.
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real world example
|
||||||
|
|
||||||
> We are designing a threat(malware) detection system. We can have different types of threats and systems. We have a requirement that
|
> We are designing a threat (malware) detection software which can analyze target systems for
|
||||||
> system should be aware of threats that are present in it. In the design we have to take into consideration that new Threat types can be
|
> threats that are present in it. In the design we have to take into consideration that new
|
||||||
> added later. Also there is a requirement that a system can filter itself based on the threats that it possesses (system acts as container-like object for threats).
|
> Threat types can be added later. Additionally, there is a requirement that the threat detection
|
||||||
>
|
> system can filter the detected threats based on different criteria (the target system acts as
|
||||||
|
> container-like object for threats).
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> We need to be able to filter different types of systems(container-like objects) based on properties of Threats that they contain.
|
> Filterer pattern is a design pattern that helps container-like objects return filtered versions
|
||||||
> Adding new properties for Threats should be easy (we still need the ability to filter by those new properties).
|
> of themselves.
|
||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
To model the threat detection example presented above we introduce `Threat` and `ThreatAwareSystem` interfaces.
|
To model the threat detection example presented above we introduce `Threat` and `ThreatAwareSystem`
|
||||||
|
interfaces.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public interface Threat {
|
public interface Threat {
|
||||||
@ -47,19 +53,26 @@ public interface ThreatAwareSystem {
|
|||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice the `filtered` method that returns instance of `Filterer` interface which is defined as:
|
Notice the `filtered` method that returns instance of `Filterer` interface which is defined as:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface Filterer<G, E> {
|
public interface Filterer<G, E> {
|
||||||
G by(Predicate<? super E> predicate);
|
G by(Predicate<? super E> predicate);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
it is used to fulfill the requirement for system to be able to filter itself based on threat properties.
|
|
||||||
The container-like object (`ThreatAwareSystem` in our case) needs to have a method that returns an instance of `Filterer`. This helper interface gives
|
|
||||||
ability to covariantly specify a lower bound of contravariant `Predicate` in the subinterfaces of interfaces representing the container-like objects.
|
|
||||||
|
|
||||||
In our example we will be able to pass a predicate that takes `? extends Threat` object and return `? extends ThreatAwareSystem`
|
It is used to fulfill the requirement for system to be able to filter itself based on threat
|
||||||
from `Filtered::by` method. A simple implementation of `ThreatAwareSystem` :
|
properties. The container-like object (`ThreatAwareSystem` in our case) needs to have a method that
|
||||||
|
returns an instance of `Filterer`. This helper interface gives ability to covariantly specify a
|
||||||
|
lower bound of contravariant `Predicate` in the subinterfaces of interfaces representing the
|
||||||
|
container-like objects.
|
||||||
|
|
||||||
|
In our example we will be able to pass a predicate that takes `? extends Threat` object and
|
||||||
|
return `? extends ThreatAwareSystem` from `Filtered::by` method. A simple implementation
|
||||||
|
of `ThreatAwareSystem`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class SimpleThreatAwareSystem implements ThreatAwareSystem {
|
public class SimpleThreatAwareSystem implements ThreatAwareSystem {
|
||||||
|
|
||||||
@ -97,15 +110,21 @@ public class SimpleThreatAwareSystem implements ThreatAwareSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
the `filtered` method is overridden to filter the threats list by given predicate.
|
|
||||||
|
|
||||||
Now if we introduce a new subtype of `Threat` interface that adds probability with which given threat can appear :
|
The `filtered` method is overridden to filter the threats list by given predicate.
|
||||||
|
|
||||||
|
Now if we introduce a new subtype of `Threat` interface that adds probability with which given
|
||||||
|
threat can appear:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public interface ProbableThreat extends Threat {
|
public interface ProbableThreat extends Threat {
|
||||||
double probability();
|
double probability();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
we can also introduce a new interface that represents a system that is aware of threats with their probabilities :
|
|
||||||
|
We can also introduce a new interface that represents a system that is aware of threats with their
|
||||||
|
probabilities:
|
||||||
|
|
||||||
````java
|
````java
|
||||||
public interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem {
|
public interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem {
|
||||||
@Override
|
@Override
|
||||||
@ -115,9 +134,12 @@ public interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem {
|
|||||||
Filterer<? extends ProbabilisticThreatAwareSystem, ? extends ProbableThreat> filtered();
|
Filterer<? extends ProbabilisticThreatAwareSystem, ? extends ProbableThreat> filtered();
|
||||||
}
|
}
|
||||||
````
|
````
|
||||||
Notice how we override the `filtered` method in `ProbabilisticThreatAwareSystem` and specify different return covariant type
|
|
||||||
by specifying different generic types. Our interfaces are clean and not cluttered by default implementations. We
|
Notice how we override the `filtered` method in `ProbabilisticThreatAwareSystem` and specify
|
||||||
we will be able to filter `ProbabilisticThreatAwareSystem` by `ProbableThreat` properties :
|
different return covariant type by specifying different generic types. Our interfaces are clean and
|
||||||
|
not cluttered by default implementations. We we will be able to filter
|
||||||
|
`ProbabilisticThreatAwareSystem` by `ProbableThreat` properties:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class SimpleProbabilisticThreatAwareSystem implements ProbabilisticThreatAwareSystem {
|
public class SimpleProbabilisticThreatAwareSystem implements ProbabilisticThreatAwareSystem {
|
||||||
|
|
||||||
@ -157,6 +179,7 @@ public class SimpleProbabilisticThreatAwareSystem implements ProbabilisticThreat
|
|||||||
```
|
```
|
||||||
|
|
||||||
Now if we want filter `ThreatAwareSystem` by threat type we can do:
|
Now if we want filter `ThreatAwareSystem` by threat type we can do:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Threat rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, "Simple-Rootkit");
|
Threat rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, "Simple-Rootkit");
|
||||||
Threat trojan = new SimpleThreat(ThreatType.TROJAN, 2, "Simple-Trojan");
|
Threat trojan = new SimpleThreat(ThreatType.TROJAN, 2, "Simple-Trojan");
|
||||||
@ -167,7 +190,9 @@ ThreatAwareSystem threatAwareSystem = new SimpleThreatAwareSystem("System-1", th
|
|||||||
ThreatAwareSystem rootkitThreatAwareSystem = threatAwareSystem.filtered()
|
ThreatAwareSystem rootkitThreatAwareSystem = threatAwareSystem.filtered()
|
||||||
.by(threat -> threat.type() == ThreatType.ROOTKIT);
|
.by(threat -> threat.type() == ThreatType.ROOTKIT);
|
||||||
```
|
```
|
||||||
or if we want to filter `ProbabilisticThreatAwareSystem` :
|
|
||||||
|
Or if we want to filter `ProbabilisticThreatAwareSystem`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
ProbableThreat malwareTroyan = new SimpleProbableThreat("Troyan-ArcBomb", 1, ThreatType.TROJAN, 0.99);
|
ProbableThreat malwareTroyan = new SimpleProbableThreat("Troyan-ArcBomb", 1, ThreatType.TROJAN, 0.99);
|
||||||
ProbableThreat rootkit = new SimpleProbableThreat("Rootkit-System", 2, ThreatType.ROOTKIT, 0.8);
|
ProbableThreat rootkit = new SimpleProbableThreat("Rootkit-System", 2, ThreatType.ROOTKIT, 0.8);
|
||||||
@ -178,27 +203,37 @@ ProbabilisticThreatAwareSystem simpleProbabilisticThreatAwareSystem =new SimpleP
|
|||||||
ProbabilisticThreatAwareSystem filtered = simpleProbabilisticThreatAwareSystem.filtered()
|
ProbabilisticThreatAwareSystem filtered = simpleProbabilisticThreatAwareSystem.filtered()
|
||||||
.by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0);
|
.by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Applicability
|
## Applicability
|
||||||
Pattern can be used when working with container-like objects that use subtyping, instead of parametrizing(generics) for extensible class structure.
|
|
||||||
It enables you to easily extend filtering ability of container-like objects as business requirements change.
|
Pattern can be used when working with container-like objects that use subtyping, instead of
|
||||||
|
parametrizing (generics) for extensible class structure. It enables you to easily extend filtering
|
||||||
|
ability of container-like objects as business requirements change.
|
||||||
|
|
||||||
## Tutorials
|
## Tutorials
|
||||||
|
|
||||||
* [Article about Filterer pattern posted on it's author's blog](https://blog.tlinkowski.pl/2018/filterer-pattern/)
|
* [Article about Filterer pattern posted on it's author's blog](https://blog.tlinkowski.pl/2018/filterer-pattern/)
|
||||||
* [Application of Filterer pattern in domain of text analysis](https://www.javacodegeeks.com/2019/02/filterer-pattern-10-steps.html)
|
* [Application of Filterer pattern in domain of text analysis](https://www.javacodegeeks.com/2019/02/filterer-pattern-10-steps.html)
|
||||||
|
|
||||||
## Known uses
|
## Known uses
|
||||||
One of the uses is present on the blog presented in [this](https://www.javacodegeeks.com/2019/02/filterer-pattern-10-steps.html) link.
|
|
||||||
It presents how to use `Filterer` pattern to create text issue analyzer with support for test cases used for unit testing.
|
One of the uses is present on the blog presented in
|
||||||
|
[this](https://www.javacodegeeks.com/2019/02/filterer-pattern-10-steps.html) link. It presents how
|
||||||
|
to use `Filterer` pattern to create text issue analyzer with support for test cases used for unit
|
||||||
|
testing.
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
Pros:
|
Pros:
|
||||||
* you can easily introduce new subtypes for container-like objects and subtypes for objects that are contained within them and still be able to filter easily be new properties of those new subtypes.
|
* You can easily introduce new subtypes for container-like objects and subtypes for objects that are contained within them and still be able to filter easily be new properties of those new subtypes.
|
||||||
|
|
||||||
Cons:
|
Cons:
|
||||||
* covariant return types mixed with generics can be sometimes tricky
|
* Covariant return types mixed with generics can be sometimes tricky
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
* Author of the pattern : [Tomasz Linkowski](https://tlinkowski.pl/)
|
* Author of the pattern : [Tomasz Linkowski](https://tlinkowski.pl/)
|
Loading…
x
Reference in New Issue
Block a user