From 015b4181145680e4b93f1fc54895aacb1238cdbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sun, 23 Aug 2020 18:03:29 +0300 Subject: [PATCH] Update README.md --- filterer/README.md | 97 +++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 31 deletions(-) diff --git a/filterer/README.md b/filterer/README.md index 9ac49d6f8..89dc87e84 100644 --- a/filterer/README.md +++ b/filterer/README.md @@ -11,27 +11,33 @@ tags: --- ## Name / classification + Filterer ## 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 + 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 -> 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 -> 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). -> +> We are designing a threat (malware) detection software which can analyze target systems for +> threats that are present in it. In the design we have to take into consideration that new +> 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 -> We need to be able to filter different types of systems(container-like objects) based on properties of Threats that they contain. -> Adding new properties for Threats should be easy (we still need the ability to filter by those new properties). +> Filterer pattern is a design pattern that helps container-like objects return filtered versions +> of themselves. **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 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 @FunctionalInterface public interface Filterer { G by(Predicate 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` -from `Filtered::by` method. A simple implementation of `ThreatAwareSystem` : +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` from `Filtered::by` method. A simple implementation +of `ThreatAwareSystem`: + ```java 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 public interface ProbableThreat extends Threat { 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 public interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem { @Override @@ -115,9 +134,12 @@ public interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem { Filterer 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 -we will be able to filter `ProbabilisticThreatAwareSystem` by `ProbableThreat` properties : + +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 we will be able to filter +`ProbabilisticThreatAwareSystem` by `ProbableThreat` properties: + ```java public class SimpleProbabilisticThreatAwareSystem implements ProbabilisticThreatAwareSystem { @@ -156,7 +178,8 @@ 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 Threat rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, "Simple-Rootkit"); Threat trojan = new SimpleThreat(ThreatType.TROJAN, 2, "Simple-Trojan"); @@ -167,7 +190,9 @@ ThreatAwareSystem threatAwareSystem = new SimpleThreatAwareSystem("System-1", th ThreatAwareSystem rootkitThreatAwareSystem = threatAwareSystem.filtered() .by(threat -> threat.type() == ThreatType.ROOTKIT); ``` -or if we want to filter `ProbabilisticThreatAwareSystem` : + +Or if we want to filter `ProbabilisticThreatAwareSystem`: + ```java ProbableThreat malwareTroyan = new SimpleProbableThreat("Troyan-ArcBomb", 1, ThreatType.TROJAN, 0.99); ProbableThreat rootkit = new SimpleProbableThreat("Rootkit-System", 2, ThreatType.ROOTKIT, 0.8); @@ -178,27 +203,37 @@ ProbabilisticThreatAwareSystem simpleProbabilisticThreatAwareSystem =new SimpleP ProbabilisticThreatAwareSystem filtered = simpleProbabilisticThreatAwareSystem.filtered() .by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0); ``` + ## Class diagram + ![Filterer](./etc/filterer.png "Filterer") ## 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 + * [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) ## 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 -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. -Cons : - * covariant return types mixed with generics can be sometimes tricky +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. + +Cons: + * Covariant return types mixed with generics can be sometimes tricky ## Credits -* Author of the pattern : [Tomasz Linkowski](https://tlinkowski.pl/) \ No newline at end of file + +* Author of the pattern : [Tomasz Linkowski](https://tlinkowski.pl/)