diff --git a/adapter/etc/adapter.png b/adapter/etc/adapter.png index 511bb5880..f43358b04 100644 Binary files a/adapter/etc/adapter.png and b/adapter/etc/adapter.png differ diff --git a/adapter/etc/adapter.ucls b/adapter/etc/adapter.ucls index 8c09f0399..290ff544e 100644 --- a/adapter/etc/adapter.ucls +++ b/adapter/etc/adapter.ucls @@ -1,61 +1,61 @@ - - - + + + - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + - - - - - - - - + + + + - + + + + + - - + + diff --git a/adapter/etc/adapter_1.png b/adapter/etc/adapter_1.png deleted file mode 100644 index 64eb34b84..000000000 Binary files a/adapter/etc/adapter_1.png and /dev/null differ diff --git a/adapter/index.md b/adapter/index.md index 36a2a0ad3..7c7dc15e5 100644 --- a/adapter/index.md +++ b/adapter/index.md @@ -15,7 +15,7 @@ tags: expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. -![alt text](./etc/adapter_1.png "Adapter") +![alt text](./etc/adapter.png "Adapter") **Applicability:** Use the Adapter pattern when diff --git a/adapter/src/main/java/com/iluwatar/adapter/App.java b/adapter/src/main/java/com/iluwatar/adapter/App.java index d2353eec4..d57cb91e4 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/App.java +++ b/adapter/src/main/java/com/iluwatar/adapter/App.java @@ -5,14 +5,23 @@ package com.iluwatar.adapter; * for an adapter. Interfaces may be incompatible but the inner functionality should suit the need. * The Adapter design pattern allows otherwise incompatible classes to work together by converting * the interface of one class into an interface expected by the clients. - * - *

There are two variations of the Adapter pattern: The class adapter implements the adaptee's + * + *

+ * There are two variations of the Adapter pattern: The class adapter implements the adaptee's * interface whereas the object adapter uses composition to contain the adaptee in the adapter * object. This example uses the object adapter approach. - * - *

The Adapter ({@link GnomeEngineer}) converts the interface of the target class ( - * {@link GoblinGlider}) into a suitable one expected by the client ({@link GnomeEngineeringManager} - * ). + * + *

+ * The Adapter ({@link BattleFishingBoat}) converts the interface of the adaptee class ( + * {@link FishingBoat}) into a suitable one expected by the client ( {@link BattleShip} ). + * + *

+ * The story of this implementation is this.
+ * Pirates are coming! we need a {@link BattleShip} to fight! We have a {@link FishingBoat} and our + * captain. We have no time to make up a new ship! we need to reuse this {@link FishingBoat}. The + * captain needs a battleship which can fire and move. The spec is in {@link BattleShip}. We will + * use the Adapter pattern to reuse {@link FishingBoat}. + * */ public class App { @@ -22,7 +31,8 @@ public class App { * @param args command line args */ public static void main(String[] args) { - Engineer manager = new GnomeEngineeringManager(new GnomeEngineer()); - manager.operateDevice(); + Captain captain = new Captain(new BattleFishingBoat()); + captain.move(); + captain.fire(); } } diff --git a/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java b/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java new file mode 100644 index 000000000..3f573337f --- /dev/null +++ b/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java @@ -0,0 +1,29 @@ +package com.iluwatar.adapter; + +/** + * + * Adapter class. Adapts the interface of the device ({@link FishingBoat}) into {@link BattleShip} + * interface expected by the client ({@link Captain}).
+ * In this case we added a new function fire to suit the interface. We are reusing the + * {@link FishingBoat} without changing itself. The Adapter class can just map the functions of the + * Adaptee or add, delete features of the Adaptee. + * + */ +public class BattleFishingBoat implements BattleShip { + + private FishingBoat boat; + + public BattleFishingBoat() { + boat = new FishingBoat(); + } + + @Override + public void fire() { + System.out.println("fire!"); + } + + @Override + public void move() { + boat.sail(); + } +} diff --git a/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java b/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java new file mode 100644 index 000000000..d4f6036e6 --- /dev/null +++ b/adapter/src/main/java/com/iluwatar/adapter/BattleShip.java @@ -0,0 +1,14 @@ +package com.iluwatar.adapter; + +/** + * The interface expected by the client.
+ * A Battleship can fire and move. + * + */ +public interface BattleShip { + + void fire(); + + void move(); + +} diff --git a/adapter/src/main/java/com/iluwatar/adapter/Captain.java b/adapter/src/main/java/com/iluwatar/adapter/Captain.java new file mode 100644 index 000000000..8c48daf69 --- /dev/null +++ b/adapter/src/main/java/com/iluwatar/adapter/Captain.java @@ -0,0 +1,33 @@ +package com.iluwatar.adapter; + +/** + * The Captain uses {@link BattleShip} to fight.
+ * This is the client in the pattern. + */ +public class Captain implements BattleShip { + + private BattleShip battleship; + + public Captain() { + + } + + public Captain(BattleShip battleship) { + this.battleship = battleship; + } + + public void setBattleship(BattleShip battleship) { + this.battleship = battleship; + } + + @Override + public void fire() { + battleship.fire(); + } + + @Override + public void move() { + battleship.move(); + } + +} diff --git a/adapter/src/main/java/com/iluwatar/adapter/Engineer.java b/adapter/src/main/java/com/iluwatar/adapter/Engineer.java deleted file mode 100644 index a973cb530..000000000 --- a/adapter/src/main/java/com/iluwatar/adapter/Engineer.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.iluwatar.adapter; - -/** - * - * Engineers can operate devices. - * - */ -public interface Engineer { - - void operateDevice(); -} diff --git a/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java b/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java new file mode 100644 index 000000000..509bb8cdb --- /dev/null +++ b/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java @@ -0,0 +1,18 @@ +package com.iluwatar.adapter; + +/** + * + * Device class (adaptee in the pattern). We want to reuse this class + * + */ +public class FishingBoat { + + public void sail() { + System.out.println("The Boat is moving to that place"); + } + + public void fish() { + System.out.println("fishing ..."); + } + +} diff --git a/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineer.java b/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineer.java deleted file mode 100644 index 70e166ac3..000000000 --- a/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.iluwatar.adapter; - -/** - * - * Adapter class. Adapts the interface of the device ({@link GoblinGlider}) into {@link Engineer} - * interface expected by the client ({@link GnomeEngineeringManager}). - * - */ -public class GnomeEngineer implements Engineer { - - private GoblinGlider glider; - - public GnomeEngineer() { - glider = new GoblinGlider(); - } - - @Override - public void operateDevice() { - glider.attachGlider(); - glider.gainSpeed(); - glider.takeOff(); - } -} diff --git a/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineeringManager.java b/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineeringManager.java deleted file mode 100644 index ff4ddb617..000000000 --- a/adapter/src/main/java/com/iluwatar/adapter/GnomeEngineeringManager.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.iluwatar.adapter; - -/** - * GnomeEngineering manager uses {@link Engineer} to operate devices. - */ -public class GnomeEngineeringManager implements Engineer { - - private Engineer engineer; - - public GnomeEngineeringManager() { - - } - - public GnomeEngineeringManager(Engineer engineer) { - this.engineer = engineer; - } - - @Override - public void operateDevice() { - engineer.operateDevice(); - } - - public void setEngineer(Engineer engineer) { - this.engineer = engineer; - } -} diff --git a/adapter/src/main/java/com/iluwatar/adapter/GoblinGlider.java b/adapter/src/main/java/com/iluwatar/adapter/GoblinGlider.java deleted file mode 100644 index 79a9acef6..000000000 --- a/adapter/src/main/java/com/iluwatar/adapter/GoblinGlider.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.iluwatar.adapter; - -/** - * - * Device class (adaptee in the pattern). - * - */ -public class GoblinGlider { - - public void attachGlider() { - System.out.println("Glider attached."); - } - - public void gainSpeed() { - System.out.println("Gaining speed."); - } - - public void takeOff() { - System.out.println("Lift-off!"); - } -} diff --git a/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java b/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java index 866bfb968..98c7cee2d 100644 --- a/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java +++ b/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java @@ -9,29 +9,22 @@ import java.util.Map; import org.junit.Before; import org.junit.Test; +import com.iluwatar.adapter.BattleFishingBoat; +import com.iluwatar.adapter.BattleShip; +import com.iluwatar.adapter.Captain; +import com.iluwatar.adapter.FishingBoat; + /** - * An adapter helps two incompatible interfaces to work together. This is the real world definition - * for an adapter. Interfaces may be incompatible but the inner functionality should suit the need. - * The Adapter design pattern allows otherwise incompatible classes to work together by converting - * the interface of one class into an interface expected by the clients. + * Test class * - *

There are two variations of the Adapter pattern: - * The class adapter implements the adaptee's - * interface whereas the object adapter uses composition to contain the adaptee in the adapter - * object. This example uses the object adapter approach. - * - *

The Adapter ({@link GnomeEngineer}) converts the interface - * of the target class ({@link GoblinGlider}) into a suitable one expected by - * the client ({@link GnomeEngineeringManager} - * ). */ public class AdapterPatternTest { private Map beans; - private static final String ENGINEER_BEAN = "engineer"; + private static final String BATTLESHIP_BEAN = "engineer"; - private static final String MANAGER_BEAN = "manager"; + private static final String CAPTAIN_BEAN = "captain"; /** * This method runs before the test execution and sets the bean objects in the beans Map. @@ -40,29 +33,34 @@ public class AdapterPatternTest { public void setup() { beans = new HashMap<>(); - GnomeEngineer gnomeEngineer = spy(new GnomeEngineer()); - beans.put(ENGINEER_BEAN, gnomeEngineer); + BattleFishingBoat battleFishingBoat = spy(new BattleFishingBoat()); + beans.put(BATTLESHIP_BEAN, battleFishingBoat); - GnomeEngineeringManager manager = new GnomeEngineeringManager(); - manager.setEngineer((GnomeEngineer) beans.get(ENGINEER_BEAN)); - beans.put(MANAGER_BEAN, manager); + Captain captain = new Captain(); + captain.setBattleship((BattleFishingBoat) beans.get(BATTLESHIP_BEAN)); + beans.put(CAPTAIN_BEAN, captain); } /** - * This test asserts that when we call operateDevice() method on a manager bean, it is internally - * calling operateDevice method on the engineer object. The Adapter ({@link GnomeEngineer}) - * converts the interface of the target class ( {@link GoblinGlider}) into a suitable one expected - * by the client ({@link GnomeEngineeringManager} ). + * This test asserts that when we use the move() method on a captain bean(client), it is + * internally calling move method on the battleship object. The Adapter ({@link BattleFishingBoat} + * ) converts the interface of the target class ( {@link FishingBoat}) into a suitable one + * expected by the client ({@link Captain} ). */ @Test public void testAdapter() { - Engineer manager = (Engineer) beans.get(MANAGER_BEAN); + BattleShip captain = (BattleShip) beans.get(CAPTAIN_BEAN); - // when manager is asked to operate device - manager.operateDevice(); + // when captain moves + captain.move(); + + // the captain internally calls the battleship object to move + BattleShip battleship = (BattleShip) beans.get(BATTLESHIP_BEAN); + verify(battleship).move(); + + // same with above with firing + captain.fire(); + verify(battleship).fire(); - // Manager internally calls the engineer object to operateDevice - Engineer engineer = (Engineer) beans.get(ENGINEER_BEAN); - verify(engineer).operateDevice(); } }