Skip to content

#567 Marker Interface pull request #572

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
May 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions marker/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target/
30 changes: 30 additions & 0 deletions marker/README.md
Original file line number Diff line number Diff line change
@@ -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)
Binary file added marker/etc/MarkerDiagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions marker/etc/MarkerDiagram.ucls
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.2.0" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
realizations="true" associations="true" dependencies="false" nesting-relationships="true" router="FAN">
<class id="1" language="java" name="Guard" project="marker" file="/marker/src/main/java/Guard.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="416" y="348"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="2" language="java" name="Permission" project="marker" file="/marker/src/main/java/Permission.java"
binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="261" y="175"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<class id="3" language="java" name="Thief" project="marker" file="/marker/src/main/java/Thief.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="236" y="355"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<realization id="4">
<end type="SOURCE" refId="1"/>
<end type="TARGET" refId="2"/>
</realization>
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</classifier-display>
<association-display labels="true" multiplicity="true"/>
</class-diagram>
41 changes: 41 additions & 0 deletions marker/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright (c) 2014-2016 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.16.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>marker</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>


</project>
48 changes: 48 additions & 0 deletions marker/src/main/java/App.java
Original file line number Diff line number Diff line change
@@ -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.
* <p>
* 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();
}
}
}

15 changes: 15 additions & 0 deletions marker/src/main/java/Guard.java
Original file line number Diff line number Diff line change
@@ -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");
}
}
6 changes: 6 additions & 0 deletions marker/src/main/java/Permission.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Interface without any methods
* Marker interface is based on that assumption
*/
public interface Permission {
}
18 changes: 18 additions & 0 deletions marker/src/main/java/Thief.java
Original file line number Diff line number Diff line change
@@ -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");
}
}
13 changes: 13 additions & 0 deletions marker/src/test/java/AppTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import org.junit.Test;

/**
* Application test
*/
public class AppTest {

@Test
public void test() {
String[] args = {};
App.main(args);
}
}
16 changes: 16 additions & 0 deletions marker/src/test/java/GuardTest.java
Original file line number Diff line number Diff line change
@@ -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));
}
}
14 changes: 14 additions & 0 deletions marker/src/test/java/ThiefTest.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
<module>converter</module>
<module>guarded-suspension</module>
<module>balking</module>
<module>marker</module>
</modules>

<dependencyManagement>
Expand Down