diff --git a/delegation/etc/delegation.png b/delegation/etc/delegation.png new file mode 100644 index 00000000..375ef4d6 Binary files /dev/null and b/delegation/etc/delegation.png differ diff --git a/delegation/etc/delegation.ucls b/delegation/etc/delegation.ucls new file mode 100644 index 00000000..e3ce0887 --- /dev/null +++ b/delegation/etc/delegation.ucls @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/delegation/index.md b/delegation/index.md new file mode 100644 index 00000000..2064a5bf --- /dev/null +++ b/delegation/index.md @@ -0,0 +1,27 @@ +--- +layout: pattern +title: Delegation +folder: delegation +permalink: /patterns/delegation/ +categories: Behavioral +tags: + - Java + - Difficulty-Beginner +--- + +**Also known as:** Proxy Pattern + +**Intent:** It is a technique where an object expresses certain behavior to the outside but in +reality delegates responsibility for implementing that behaviour to an associated object. + +![alt text](./etc/delegation.png "Delegate") + +**Applicability:** Use the Delegate pattern in order to achieve the following + +* Reduce the coupling of methods to their class +* Components that behave identically, but realize that this situation can change in the future. + +**Credits** + +* [Delegate Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Delegation_pattern) +* [Proxy Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Proxy_pattern) \ No newline at end of file diff --git a/delegation/pom.xml b/delegation/pom.xml new file mode 100644 index 00000000..4c9d1688 --- /dev/null +++ b/delegation/pom.xml @@ -0,0 +1,27 @@ + + + + + java-design-patterns + com.iluwatar + 1.9.0-SNAPSHOT + + 4.0.0 + + delegation + + + + junit + junit + test + + + com.github.stefanbirkner + system-rules + test + + + \ No newline at end of file diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/App.java b/delegation/src/main/java/com/iluwatar/delegation/simple/App.java new file mode 100644 index 00000000..050380c1 --- /dev/null +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/App.java @@ -0,0 +1,38 @@ +package com.iluwatar.delegation.simple; + +import com.iluwatar.delegation.simple.printers.CanonPrinter; +import com.iluwatar.delegation.simple.printers.EpsonPrinter; +import com.iluwatar.delegation.simple.printers.HpPrinter; + +/** + * The delegate pattern provides a mechanism to abstract away the implementation and control of the desired action. + * The class being called in this case {@link PrinterController} is not responsible for the actual desired action, + * but is actually delegated to a helper class either {@link CanonPrinter}, {@link EpsonPrinter} or {@link HpPrinter}. + * The consumer does not have or require knowledge of the actual class carrying out the action, only the + * container on which they are calling. + * + * In this example the delegates are {@link EpsonPrinter}, {@link HpPrinter} and {@link CanonPrinter} they all implement + * {@link Printer}. The {@link PrinterController} class also implements {@link Printer}. However neither provide the + * functionality of {@link Printer} by printing to the screen, they actually call upon the instance of {@link Printer} + * that they were instantiated with. Therefore delegating the behaviour to another class. + */ +public class App { + + public static final String MESSAGE_TO_PRINT = "hello world"; + + /** + * Program entry point + * + * @param args command line args + */ + public static void main(String[] args) { + PrinterController hpPrinterController = new PrinterController(new HpPrinter()); + PrinterController canonPrinterController = new PrinterController(new CanonPrinter()); + PrinterController epsonPrinterController = new PrinterController(new EpsonPrinter()); + + hpPrinterController.print(MESSAGE_TO_PRINT); + canonPrinterController.print(MESSAGE_TO_PRINT); + epsonPrinterController.print(MESSAGE_TO_PRINT); + } + +} diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java b/delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java new file mode 100644 index 00000000..91531dfc --- /dev/null +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java @@ -0,0 +1,23 @@ +package com.iluwatar.delegation.simple; + +import com.iluwatar.delegation.simple.printers.CanonPrinter; +import com.iluwatar.delegation.simple.printers.EpsonPrinter; +import com.iluwatar.delegation.simple.printers.HpPrinter; + +/** + * Interface that both the Controller and the Delegate will implement. + * + * @see CanonPrinter + * @see EpsonPrinter + * @see HpPrinter + */ +public interface Printer { + + /** + * Method that takes a String to print to the screen. This will be implemented on both the + * controller and the delegate allowing the controller to call the same method on the delegate class. + * + * @param message to be printed to the screen + */ + void print(final String message); +} diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java b/delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java new file mode 100644 index 00000000..d237f087 --- /dev/null +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java @@ -0,0 +1,23 @@ +package com.iluwatar.delegation.simple; + +public class PrinterController implements Printer { + + private final Printer printer; + + public PrinterController(Printer printer) { + this.printer = printer; + } + + /** + * This method is implemented from {@link Printer} however instead on providing an + * implementation, it instead calls upon the class passed through the constructor. This is the delegate, + * hence the pattern. Therefore meaning that the caller does not care of the implementing class only the owning + * controller. + * + * @param message to be printed to the screen + */ + @Override + public void print(String message) { + printer.print(message); + } +} diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java new file mode 100644 index 00000000..ef638642 --- /dev/null +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java @@ -0,0 +1,21 @@ +package com.iluwatar.delegation.simple.printers; + +import com.iluwatar.delegation.simple.Printer; + +/** + * Specialised Implementation of {@link Printer} for a Canon Printer, in + * this case the message to be printed is appended to "Canon Printer : " + * + * @see Printer + */ +public class CanonPrinter implements Printer { + + /** + * {@inheritDoc} + */ + @Override + public void print(String message) { + System.out.print("Canon Printer : " + message); + } + +} diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java new file mode 100644 index 00000000..780d12bc --- /dev/null +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java @@ -0,0 +1,21 @@ +package com.iluwatar.delegation.simple.printers; + +import com.iluwatar.delegation.simple.Printer; + +/** + * Specialised Implementation of {@link Printer} for a Epson Printer, in + * this case the message to be printed is appended to "Epson Printer : " + * + * @see Printer + */ +public class EpsonPrinter implements Printer { + + /** + * {@inheritDoc} + */ + @Override + public void print(String message) { + System.out.print("Epson Printer : " + message); + } + +} diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java new file mode 100644 index 00000000..be8845ec --- /dev/null +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java @@ -0,0 +1,21 @@ +package com.iluwatar.delegation.simple.printers; + +import com.iluwatar.delegation.simple.Printer; + +/** + * Specialised Implementation of {@link Printer} for a HP Printer, in + * this case the message to be printed is appended to "HP Printer : " + * + * @see Printer + */ +public class HpPrinter implements Printer { + + /** + * {@inheritDoc} + */ + @Override + public void print(String message) { + System.out.print("HP Printer : " + message); + } + +} diff --git a/delegation/src/test/java/com/iluwatar/delegation/simple/AppTest.java b/delegation/src/test/java/com/iluwatar/delegation/simple/AppTest.java new file mode 100644 index 00000000..189baa85 --- /dev/null +++ b/delegation/src/test/java/com/iluwatar/delegation/simple/AppTest.java @@ -0,0 +1,13 @@ +package com.iluwatar.delegation.simple; + +import org.junit.Test; + +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } + +} diff --git a/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java b/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java new file mode 100644 index 00000000..9442b303 --- /dev/null +++ b/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java @@ -0,0 +1,43 @@ +package com.iluwatar.delegation.simple; + +import com.iluwatar.delegation.simple.printers.CanonPrinter; +import com.iluwatar.delegation.simple.printers.EpsonPrinter; +import com.iluwatar.delegation.simple.printers.HpPrinter; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.SystemOutRule; + +import static org.junit.Assert.assertEquals; + +public class DelegateTest { + + private static final String MESSAGE = "Test Message Printed"; + + @Rule + public final SystemOutRule systemOutRule = new SystemOutRule().enableLog(); + + @Test + public void testCanonPrinter() throws Exception { + PrinterController printerController = new PrinterController(new CanonPrinter()); + printerController.print(MESSAGE); + + assertEquals("Canon Printer : Test Message Printed", systemOutRule.getLog()); + } + + @Test + public void testHpPrinter() throws Exception { + PrinterController printerController = new PrinterController(new HpPrinter()); + printerController.print(MESSAGE); + + assertEquals("HP Printer : Test Message Printed", systemOutRule.getLog()); + } + + @Test + public void testEpsonPrinter() throws Exception { + PrinterController printerController = new PrinterController(new EpsonPrinter()); + printerController.print(MESSAGE); + + assertEquals("Epson Printer : Test Message Printed", systemOutRule.getLog()); + } + +} diff --git a/pom.xml b/pom.xml index 8297b7e0..13da4198 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ 2.15.3 1.2.17 18.0 + 1.14.0 abstract-factory @@ -88,6 +89,7 @@ reactor caching publish-subscribe + delegation @@ -154,6 +156,12 @@ guava ${guava.version} + + com.github.stefanbirkner + system-rules + ${systemrules.version} + test +