diff --git a/marker/.gitignore b/marker/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/marker/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/marker/README.md b/marker/README.md new file mode 100644 index 000000000..5bcdf9664 --- /dev/null +++ b/marker/README.md @@ -0,0 +1,30 @@ +--- +layout: pattern +title: Marker Interface +folder: marker +permalink: /patterns/marker/ +categories: Design +tags: + - Java + - Difficulty-Beginner +--- + +## Intent +Using empty interfaces as markers to distinguish special treated objects. + +![alt text](./etc/MarkerDiagram.png "Marker Interface") + +## Applicability +Use the Marker Interface pattern when + +* you want to identify the special objects from normal objects (to treat them differently) +* you want to mark that some object is available for certain sort of operations + +## Real world examples + +* [javase.8.docs.api.java.io.Serializable](https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html) +* [javase.8.docs.api.java.lang.Cloneable](https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html) + +## Credits + +* [Effective Java 2nd Edition by Joshua Bloch](https://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683) diff --git a/marker/etc/MarkerDiagram.png b/marker/etc/MarkerDiagram.png new file mode 100644 index 000000000..6ed4f9c56 Binary files /dev/null and b/marker/etc/MarkerDiagram.png differ diff --git a/marker/etc/MarkerDiagram.ucls b/marker/etc/MarkerDiagram.ucls new file mode 100644 index 000000000..0f8376e40 --- /dev/null +++ b/marker/etc/MarkerDiagram.ucls @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/marker/pom.xml b/marker/pom.xml new file mode 100644 index 000000000..2842bd739 --- /dev/null +++ b/marker/pom.xml @@ -0,0 +1,41 @@ + + + + + java-design-patterns + com.iluwatar + 1.16.0-SNAPSHOT + + 4.0.0 + + marker + + + junit + junit + test + + + + + diff --git a/marker/src/main/java/App.java b/marker/src/main/java/App.java new file mode 100644 index 000000000..7abdda8c4 --- /dev/null +++ b/marker/src/main/java/App.java @@ -0,0 +1,48 @@ +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by Alexis on 28-Apr-17. + * With Marker interface idea is to make empty interface and extend it. + * Basically it is just to identify the special objects from normal objects. + * Like in case of serialization , objects that need to be serialized must implement serializable interface + * (it is empty interface) and down the line writeObject() method must be checking + * if it is a instance of serializable or not. + *

+ * Marker interface vs annotation + * Marker interfaces and marker annotations both have their uses, + * neither of them is obsolete or always better then the other one. + * If you want to define a type that does not have any new methods associated with it, + * a marker interface is the way to go. + * If you want to mark program elements other than classes and interfaces, + * to allow for the possibility of adding more information to the marker in the future, + * or to fit the marker into a framework that already makes heavy use of annotation types, + * then a marker annotation is the correct choice + */ +public class App { + + /** + * Program entry point + * + * @param args command line args + */ + public static void main(String[] args) { + + final Logger logger = LoggerFactory.getLogger(App.class); + Guard guard = new Guard(); + Thief thief = new Thief(); + + if (guard instanceof Permission) { + guard.enter(); + } else { + logger.info("You have no permission to enter, please leave this area"); + } + + if (thief instanceof Permission) { + thief.steal(); + } else { + thief.doNothing(); + } + } +} + diff --git a/marker/src/main/java/Guard.java b/marker/src/main/java/Guard.java new file mode 100644 index 000000000..14016f0b1 --- /dev/null +++ b/marker/src/main/java/Guard.java @@ -0,0 +1,15 @@ +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class defining Guard + */ +public class Guard implements Permission { + + private static final Logger LOGGER = LoggerFactory.getLogger(Guard.class); + + protected static void enter() { + + LOGGER.info("You can enter"); + } +} diff --git a/marker/src/main/java/Permission.java b/marker/src/main/java/Permission.java new file mode 100644 index 000000000..c6e78c49d --- /dev/null +++ b/marker/src/main/java/Permission.java @@ -0,0 +1,6 @@ +/** + * Interface without any methods + * Marker interface is based on that assumption + */ +public interface Permission { +} diff --git a/marker/src/main/java/Thief.java b/marker/src/main/java/Thief.java new file mode 100644 index 000000000..9105057e3 --- /dev/null +++ b/marker/src/main/java/Thief.java @@ -0,0 +1,18 @@ +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class defining Thief + */ +public class Thief { + + private static final Logger LOGGER = LoggerFactory.getLogger(Thief.class); + + protected static void steal() { + LOGGER.info("Steal valuable items"); + } + + protected static void doNothing() { + LOGGER.info("Pretend nothing happened and just leave"); + } +} diff --git a/marker/src/test/java/AppTest.java b/marker/src/test/java/AppTest.java new file mode 100644 index 000000000..55fb2a17f --- /dev/null +++ b/marker/src/test/java/AppTest.java @@ -0,0 +1,13 @@ +import org.junit.Test; + +/** + * Application test + */ +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } +} diff --git a/marker/src/test/java/GuardTest.java b/marker/src/test/java/GuardTest.java new file mode 100644 index 000000000..8b33b6e7f --- /dev/null +++ b/marker/src/test/java/GuardTest.java @@ -0,0 +1,16 @@ +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertThat; + +/** + * Guard test + */ +public class GuardTest { + + @Test + public void testGuard() { + Guard guard = new Guard(); + assertThat(guard, instanceOf(Permission.class)); + } +} \ No newline at end of file diff --git a/marker/src/test/java/ThiefTest.java b/marker/src/test/java/ThiefTest.java new file mode 100644 index 000000000..71fe82b68 --- /dev/null +++ b/marker/src/test/java/ThiefTest.java @@ -0,0 +1,14 @@ +import org.junit.Test; + +import static org.junit.Assert.assertFalse; + +/** + * Thief test + */ +public class ThiefTest { + @Test + public void testThief() { + Thief thief = new Thief(); + assertFalse(thief instanceof Permission); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index d49a5aa24..f843b80e9 100644 --- a/pom.xml +++ b/pom.xml @@ -140,6 +140,7 @@ converter guarded-suspension balking + marker