diff --git a/extension-objects/README.md b/extension-objects/README.md
new file mode 100644
index 000000000..9b5c93a22
--- /dev/null
+++ b/extension-objects/README.md
@@ -0,0 +1,28 @@
+---
+layout: pattern
+title: Extension objects
+folder: extension-objects
+permalink: /patterns/extension-objects/
+categories: Behavioral
+tags:
+ - Java
+ - Difficulty-Intermediate
+---
+
+## Intent
+Anticipate that an object’s interface needs to be extended in the future. Additional
+interfaces are defined by extension objects.
+
+
+
+## Applicability
+Use the Extension Objects pattern when:
+
+* you need to support the addition of new or unforeseen interfaces to existing classes and you don't want to impact clients that don't need this new interface. Extension Objects lets you keep related operations together by defining them in a separate class
+* a class representing a key abstraction plays different roles for different clients. The number of roles the class can play should be open-ended. There is a need to preserve the key abstraction itself. For example, a customer object is still a customer object even if different subsystems view it differently.
+* a class should be extensible with new behavior without subclassing from it.
+
+## Real world examples
+
+* [OpenDoc](https://en.wikipedia.org/wiki/OpenDoc)
+* [Object Linking and Embedding](https://en.wikipedia.org/wiki/Object_Linking_and_Embedding)
diff --git a/extension-objects/etc/extension_obj.png b/extension-objects/etc/extension_obj.png
new file mode 100644
index 000000000..a2b750e9d
Binary files /dev/null and b/extension-objects/etc/extension_obj.png differ
diff --git a/extension-objects/etc/extension_obj.ucls b/extension-objects/etc/extension_obj.ucls
new file mode 100644
index 000000000..9471caa83
--- /dev/null
+++ b/extension-objects/etc/extension_obj.ucls
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extension-objects/pom.xml b/extension-objects/pom.xml
new file mode 100644
index 000000000..4c0b0a230
--- /dev/null
+++ b/extension-objects/pom.xml
@@ -0,0 +1,21 @@
+
+
+
+ java-design-patterns
+ com.iluwatar
+ 1.16.0-SNAPSHOT
+
+ 4.0.0
+
+ extension-objects
+
+
+ junit
+ junit
+ test
+
+
+
+
diff --git a/extension-objects/src/main/java/App.java b/extension-objects/src/main/java/App.java
new file mode 100644
index 000000000..91ee129ee
--- /dev/null
+++ b/extension-objects/src/main/java/App.java
@@ -0,0 +1,62 @@
+import abstractextensions.CommanderExtension;
+import abstractextensions.SergeantExtension;
+import abstractextensions.SoldierExtension;
+import units.CommanderUnit;
+import units.SergeantUnit;
+import units.SoldierUnit;
+import units.Unit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Anticipate that an object’s interface needs to be extended in the future.
+ * Additional interfaces are defined by extension objects.
+ */
+public class App {
+
+ /**
+ * Program entry point
+ *
+ * @param args command line args
+ */
+ public static void main(String[] args) {
+
+ //Create 3 different units
+ Unit soldierUnit = new SoldierUnit("SoldierUnit1");
+ Unit sergeantUnit = new SergeantUnit("SergeantUnit1");
+ Unit commanderUnit = new CommanderUnit("CommanderUnit1");
+
+ //check for each unit to have an extension
+ checkExtensionsForUnit(soldierUnit);
+ checkExtensionsForUnit(sergeantUnit);
+ checkExtensionsForUnit(commanderUnit);
+
+ }
+
+ private static void checkExtensionsForUnit(Unit unit) {
+ final Logger logger = LoggerFactory.getLogger(App.class);
+
+ SoldierExtension soldierExtension = (SoldierExtension) unit.getUnitExtension("SoldierExtension");
+ SergeantExtension sergeantExtension = (SergeantExtension) unit.getUnitExtension("SergeantExtension");
+ CommanderExtension commanderExtension = (CommanderExtension) unit.getUnitExtension("CommanderExtension");
+
+ //if unit have extension call the method
+ if (soldierExtension != null) {
+ soldierExtension.soldierReady();
+ } else {
+ logger.info(unit.getName() + " without SoldierExtension");
+ }
+
+ if (sergeantExtension != null) {
+ sergeantExtension.sergeantReady();
+ } else {
+ logger.info(unit.getName() + " without SergeantExtension");
+ }
+
+ if (commanderExtension != null) {
+ commanderExtension.commanderReady();
+ } else {
+ logger.info(unit.getName() + " without CommanderExtension");
+ }
+ }
+}
diff --git a/extension-objects/src/main/java/abstractextensions/CommanderExtension.java b/extension-objects/src/main/java/abstractextensions/CommanderExtension.java
new file mode 100644
index 000000000..7f8b3ef25
--- /dev/null
+++ b/extension-objects/src/main/java/abstractextensions/CommanderExtension.java
@@ -0,0 +1,9 @@
+package abstractextensions;
+
+/**
+ * Interface with their method
+ */
+public interface CommanderExtension extends UnitExtension {
+
+ void commanderReady();
+}
diff --git a/extension-objects/src/main/java/abstractextensions/SergeantExtension.java b/extension-objects/src/main/java/abstractextensions/SergeantExtension.java
new file mode 100644
index 000000000..953d15fc0
--- /dev/null
+++ b/extension-objects/src/main/java/abstractextensions/SergeantExtension.java
@@ -0,0 +1,9 @@
+package abstractextensions;
+
+/**
+ * Interface with their method
+ */
+public interface SergeantExtension extends UnitExtension {
+
+ void sergeantReady();
+}
diff --git a/extension-objects/src/main/java/abstractextensions/SoldierExtension.java b/extension-objects/src/main/java/abstractextensions/SoldierExtension.java
new file mode 100644
index 000000000..9d995bc0e
--- /dev/null
+++ b/extension-objects/src/main/java/abstractextensions/SoldierExtension.java
@@ -0,0 +1,8 @@
+package abstractextensions;
+
+/**
+ * Interface with their method
+ */
+public interface SoldierExtension extends UnitExtension {
+ void soldierReady();
+}
diff --git a/extension-objects/src/main/java/abstractextensions/UnitExtension.java b/extension-objects/src/main/java/abstractextensions/UnitExtension.java
new file mode 100644
index 000000000..073f49a48
--- /dev/null
+++ b/extension-objects/src/main/java/abstractextensions/UnitExtension.java
@@ -0,0 +1,7 @@
+package abstractextensions;
+
+/**
+ * Other Extensions will extend this interface
+ */
+public interface UnitExtension {
+}
diff --git a/extension-objects/src/main/java/concreteextensions/Commander.java b/extension-objects/src/main/java/concreteextensions/Commander.java
new file mode 100644
index 000000000..a18f5412e
--- /dev/null
+++ b/extension-objects/src/main/java/concreteextensions/Commander.java
@@ -0,0 +1,25 @@
+package concreteextensions;
+
+import abstractextensions.CommanderExtension;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import units.CommanderUnit;
+
+/**
+ * Class defining Commander
+ */
+public class Commander implements CommanderExtension {
+
+ private CommanderUnit unit;
+
+ public Commander(CommanderUnit commanderUnit) {
+ this.unit = commanderUnit;
+ }
+
+ final Logger logger = LoggerFactory.getLogger(Commander.class);
+
+ @Override
+ public void commanderReady() {
+ logger.info("[Commander] " + unit.getName() + " is ready!");
+ }
+}
diff --git a/extension-objects/src/main/java/concreteextensions/Sergeant.java b/extension-objects/src/main/java/concreteextensions/Sergeant.java
new file mode 100644
index 000000000..0f92a2170
--- /dev/null
+++ b/extension-objects/src/main/java/concreteextensions/Sergeant.java
@@ -0,0 +1,25 @@
+package concreteextensions;
+
+import abstractextensions.SergeantExtension;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import units.SergeantUnit;
+
+/**
+ * Class defining Sergeant
+ */
+public class Sergeant implements SergeantExtension {
+
+ private SergeantUnit unit;
+
+ public Sergeant(SergeantUnit sergeantUnit) {
+ this.unit = sergeantUnit;
+ }
+
+ final Logger logger = LoggerFactory.getLogger(Sergeant.class);
+
+ @Override
+ public void sergeantReady() {
+ logger.info("[Sergeant] " + unit.getName() + " is ready! ");
+ }
+}
diff --git a/extension-objects/src/main/java/concreteextensions/Soldier.java b/extension-objects/src/main/java/concreteextensions/Soldier.java
new file mode 100644
index 000000000..790e78fb2
--- /dev/null
+++ b/extension-objects/src/main/java/concreteextensions/Soldier.java
@@ -0,0 +1,25 @@
+package concreteextensions;
+
+import abstractextensions.SoldierExtension;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import units.SoldierUnit;
+
+/**
+ * Class defining Soldier
+ */
+public class Soldier implements SoldierExtension {
+
+ private SoldierUnit unit;
+
+ public Soldier(SoldierUnit soldierUnit) {
+ this.unit = soldierUnit;
+ }
+
+ final Logger logger = LoggerFactory.getLogger(Soldier.class);
+
+ @Override
+ public void soldierReady() {
+ logger.info("[Solider] " + unit.getName() + " is ready!");
+ }
+}
diff --git a/extension-objects/src/main/java/units/CommanderUnit.java b/extension-objects/src/main/java/units/CommanderUnit.java
new file mode 100644
index 000000000..06ad6e127
--- /dev/null
+++ b/extension-objects/src/main/java/units/CommanderUnit.java
@@ -0,0 +1,27 @@
+package units;
+
+import abstractextensions.UnitExtension;
+import concreteextensions.Commander;
+
+/**
+ * Class defining CommanderUnit
+ */
+public class CommanderUnit extends Unit {
+
+ public CommanderUnit(String name) {
+ super(name);
+ }
+
+ @Override
+ public UnitExtension getUnitExtension(String extensionName) {
+
+ if (extensionName.equals("CommanderExtension")) {
+ if (unitExtension == null) {
+ unitExtension = new Commander(this);
+ }
+ return unitExtension;
+ }
+
+ return super.getUnitExtension(extensionName);
+ }
+}
diff --git a/extension-objects/src/main/java/units/SergeantUnit.java b/extension-objects/src/main/java/units/SergeantUnit.java
new file mode 100644
index 000000000..a84631b12
--- /dev/null
+++ b/extension-objects/src/main/java/units/SergeantUnit.java
@@ -0,0 +1,27 @@
+package units;
+
+import abstractextensions.UnitExtension;
+import concreteextensions.Sergeant;
+
+/**
+ * Class defining SergeantUnit
+ */
+public class SergeantUnit extends Unit {
+
+ public SergeantUnit(String name) {
+ super(name);
+ }
+
+ @Override
+ public UnitExtension getUnitExtension(String extensionName) {
+
+ if (extensionName.equals("SergeantExtension")) {
+ if (unitExtension == null) {
+ unitExtension = new Sergeant(this);
+ }
+ return unitExtension;
+ }
+
+ return super.getUnitExtension(extensionName);
+ }
+}
diff --git a/extension-objects/src/main/java/units/SoldierUnit.java b/extension-objects/src/main/java/units/SoldierUnit.java
new file mode 100644
index 000000000..957f68b86
--- /dev/null
+++ b/extension-objects/src/main/java/units/SoldierUnit.java
@@ -0,0 +1,27 @@
+package units;
+
+import abstractextensions.UnitExtension;
+import concreteextensions.Soldier;
+
+/**
+ * Class defining SoldierUnit
+ */
+public class SoldierUnit extends Unit {
+
+ public SoldierUnit(String name) {
+ super(name);
+ }
+
+ @Override
+ public UnitExtension getUnitExtension(String extensionName) {
+
+ if (extensionName.equals("SoldierExtension")) {
+ if (unitExtension == null) {
+ unitExtension = new Soldier(this);
+ }
+
+ return unitExtension;
+ }
+ return super.getUnitExtension(extensionName);
+ }
+}
diff --git a/extension-objects/src/main/java/units/Unit.java b/extension-objects/src/main/java/units/Unit.java
new file mode 100644
index 000000000..411a3e3ff
--- /dev/null
+++ b/extension-objects/src/main/java/units/Unit.java
@@ -0,0 +1,28 @@
+package units;
+
+import abstractextensions.UnitExtension;
+
+/**
+ * Class defining Unit, other units will extend this class
+ */
+public class Unit {
+
+ private String name;
+ protected UnitExtension unitExtension = null;
+
+ public Unit(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public UnitExtension getUnitExtension(String extensionName) {
+ return null;
+ }
+}
diff --git a/extension-objects/src/test/java/AppTest.java b/extension-objects/src/test/java/AppTest.java
new file mode 100644
index 000000000..287ffc131
--- /dev/null
+++ b/extension-objects/src/test/java/AppTest.java
@@ -0,0 +1,14 @@
+import org.junit.Test;
+
+/**
+ * Created by Srdjan on 03-May-17.
+ */
+public class AppTest {
+ @Test
+ public void main() throws Exception {
+
+ String[] args = {};
+ App.main(args);
+ }
+
+}
\ No newline at end of file
diff --git a/extension-objects/src/test/java/concreteextensions/CommanderTest.java b/extension-objects/src/test/java/concreteextensions/CommanderTest.java
new file mode 100644
index 000000000..82079c69a
--- /dev/null
+++ b/extension-objects/src/test/java/concreteextensions/CommanderTest.java
@@ -0,0 +1,17 @@
+package concreteextensions;
+
+import org.junit.Test;
+import units.CommanderUnit;
+
+/**
+ * Created by Srdjan on 03-May-17.
+ */
+public class CommanderTest {
+ @Test
+ public void commanderReady() throws Exception {
+ final Commander commander = new Commander(new CommanderUnit("CommanderUnitTest"));
+
+ commander.commanderReady();
+ }
+
+}
\ No newline at end of file
diff --git a/extension-objects/src/test/java/concreteextensions/SergeantTest.java b/extension-objects/src/test/java/concreteextensions/SergeantTest.java
new file mode 100644
index 000000000..7b29057f6
--- /dev/null
+++ b/extension-objects/src/test/java/concreteextensions/SergeantTest.java
@@ -0,0 +1,17 @@
+package concreteextensions;
+
+import org.junit.Test;
+import units.SergeantUnit;
+
+/**
+ * Created by Srdjan on 03-May-17.
+ */
+public class SergeantTest {
+ @Test
+ public void sergeantReady() throws Exception {
+ final Sergeant sergeant = new Sergeant(new SergeantUnit("SergeantUnitTest"));
+
+ sergeant.sergeantReady();
+ }
+
+}
\ No newline at end of file
diff --git a/extension-objects/src/test/java/concreteextensions/SoldierTest.java b/extension-objects/src/test/java/concreteextensions/SoldierTest.java
new file mode 100644
index 000000000..02a3144c2
--- /dev/null
+++ b/extension-objects/src/test/java/concreteextensions/SoldierTest.java
@@ -0,0 +1,17 @@
+package concreteextensions;
+
+import org.junit.Test;
+import units.SoldierUnit;
+
+/**
+ * Created by Srdjan on 03-May-17.
+ */
+public class SoldierTest {
+ @Test
+ public void soldierReady() throws Exception {
+ final Soldier soldier = new Soldier(new SoldierUnit("SoldierUnitTest"));
+
+ soldier.soldierReady();
+ }
+
+}
\ No newline at end of file
diff --git a/extension-objects/src/test/java/units/CommanderUnitTest.java b/extension-objects/src/test/java/units/CommanderUnitTest.java
new file mode 100644
index 000000000..75bf5f4fc
--- /dev/null
+++ b/extension-objects/src/test/java/units/CommanderUnitTest.java
@@ -0,0 +1,23 @@
+package units;
+
+import abstractextensions.CommanderExtension;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Created by Srdjan on 03-May-17.
+ */
+public class CommanderUnitTest {
+ @Test
+ public void getUnitExtension() throws Exception {
+
+ final Unit unit = new CommanderUnit("CommanderUnitName");
+
+ assertNull(unit.getUnitExtension("SoldierExtension"));
+ assertNull(unit.getUnitExtension("SergeantExtension"));
+ assertNotNull((CommanderExtension) unit.getUnitExtension("CommanderExtension"));
+ }
+
+}
\ No newline at end of file
diff --git a/extension-objects/src/test/java/units/SergeantUnitTest.java b/extension-objects/src/test/java/units/SergeantUnitTest.java
new file mode 100644
index 000000000..af2eca7cc
--- /dev/null
+++ b/extension-objects/src/test/java/units/SergeantUnitTest.java
@@ -0,0 +1,23 @@
+package units;
+
+import abstractextensions.SergeantExtension;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Created by Srdjan on 03-May-17.
+ */
+public class SergeantUnitTest {
+ @Test
+ public void getUnitExtension() throws Exception {
+
+ final Unit unit = new SergeantUnit("SergeantUnitName");
+
+ assertNull(unit.getUnitExtension("SoldierExtension"));
+ assertNotNull((SergeantExtension) unit.getUnitExtension("SergeantExtension"));
+ assertNull(unit.getUnitExtension("CommanderExtension"));
+ }
+
+}
\ No newline at end of file
diff --git a/extension-objects/src/test/java/units/SoldierUnitTest.java b/extension-objects/src/test/java/units/SoldierUnitTest.java
new file mode 100644
index 000000000..19b0c2923
--- /dev/null
+++ b/extension-objects/src/test/java/units/SoldierUnitTest.java
@@ -0,0 +1,25 @@
+package units;
+
+import abstractextensions.SoldierExtension;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Created by Srdjan on 03-May-17.
+ */
+public class SoldierUnitTest {
+ @Test
+ public void getUnitExtension() throws Exception {
+
+ final Unit unit = new SoldierUnit("SoldierUnitName");
+
+ assertNotNull((SoldierExtension) unit.getUnitExtension("SoldierExtension"));
+ assertNull(unit.getUnitExtension("SergeantExtension"));
+ assertNull(unit.getUnitExtension("CommanderExtension"));
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/extension-objects/src/test/java/units/UnitTest.java b/extension-objects/src/test/java/units/UnitTest.java
new file mode 100644
index 000000000..773b485ce
--- /dev/null
+++ b/extension-objects/src/test/java/units/UnitTest.java
@@ -0,0 +1,30 @@
+package units;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Created by Srdjan on 03-May-17.
+ */
+public class UnitTest {
+
+ @Test
+ public void testConstGetSet() throws Exception {
+ final String name = "testName";
+ final Unit unit = new Unit(name);
+ assertEquals(name, unit.getName());
+
+ final String newName = "newName";
+ unit.setName(newName);
+ assertEquals(newName, unit.getName());
+
+
+ assertNull(unit.getUnitExtension(""));
+ assertNull(unit.getUnitExtension("SoldierExtension"));
+ assertNull(unit.getUnitExtension("SergeantExtension"));
+ assertNull(unit.getUnitExtension("CommanderExtension"));
+ }
+
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index f843b80e9..054659aef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -140,7 +140,9 @@
converter
guarded-suspension
balking
+ extension-objects
marker
+