From a5ec376089b17ab35cbcc3dd63a411ee188a9f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Tue, 22 Aug 2017 09:11:18 +0300 Subject: [PATCH 1/3] Work on improved Bridge example --- bridge/etc/bridge.png | Bin 53487 -> 0 bytes bridge/etc/bridge.ucls | 157 ------------------ bridge/etc/bridge.urm.puml | 92 ---------- .../main/java/com/iluwatar/bridge/App.java | 42 ++--- .../iluwatar/bridge/BlindingMagicWeapon.java | 59 ------- ...gMagicWeaponImpl.java => Enchantment.java} | 11 +- ...{Excalibur.java => FlyingEnchantment.java} | 23 +-- .../{FlyingMagicWeapon.java => Hammer.java} | 31 ++-- .../java/com/iluwatar/bridge/MagicWeapon.java | 47 ------ .../com/iluwatar/bridge/MagicWeaponImpl.java | 38 ----- .../java/com/iluwatar/bridge/Mjollnir.java | 56 ------- ...ringer.java => SoulEatingEnchantment.java} | 23 +-- .../bridge/SoulEatingMagicWeaponImpl.java | 34 ---- ...{SoulEatingMagicWeapon.java => Sword.java} | 32 ++-- ...indingMagicWeaponImpl.java => Weapon.java} | 11 +- .../bridge/BlindingMagicWeaponTest.java | 16 +- .../bridge/FlyingMagicWeaponTest.java | 16 +- .../com/iluwatar/bridge/MagicWeaponTest.java | 36 ++-- .../bridge/SoulEatingMagicWeaponTest.java | 16 +- pom.xml | 1 + 20 files changed, 129 insertions(+), 612 deletions(-) delete mode 100644 bridge/etc/bridge.png delete mode 100644 bridge/etc/bridge.ucls delete mode 100644 bridge/etc/bridge.urm.puml delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeapon.java rename bridge/src/main/java/com/iluwatar/bridge/{FlyingMagicWeaponImpl.java => Enchantment.java} (90%) rename bridge/src/main/java/com/iluwatar/bridge/{Excalibur.java => FlyingEnchantment.java} (73%) rename bridge/src/main/java/com/iluwatar/bridge/{FlyingMagicWeapon.java => Hammer.java} (71%) delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/MagicWeapon.java delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/MagicWeaponImpl.java delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java rename bridge/src/main/java/com/iluwatar/bridge/{Stormbringer.java => SoulEatingEnchantment.java} (76%) delete mode 100644 bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeaponImpl.java rename bridge/src/main/java/com/iluwatar/bridge/{SoulEatingMagicWeapon.java => Sword.java} (71%) rename bridge/src/main/java/com/iluwatar/bridge/{BlindingMagicWeaponImpl.java => Weapon.java} (89%) diff --git a/bridge/etc/bridge.png b/bridge/etc/bridge.png deleted file mode 100644 index 00d3e611c1f72e1b3411c3c5b327f81a49f3a78e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53487 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 Sl~`f)|MIdbw@Rc<9{(RdGq(Q# diff --git a/bridge/etc/bridge.ucls b/bridge/etc/bridge.ucls deleted file mode 100644 index 2eda6e1d1..000000000 --- a/bridge/etc/bridge.ucls +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/bridge/etc/bridge.urm.puml b/bridge/etc/bridge.urm.puml deleted file mode 100644 index 82e3b14af..000000000 --- a/bridge/etc/bridge.urm.puml +++ /dev/null @@ -1,92 +0,0 @@ -@startuml -package com.iluwatar.bridge { - class App { - + App() - + main(args : String[]) {static} - } - class BlindingMagicWeapon { - + BlindingMagicWeapon(imp : BlindingMagicWeaponImpl) - + blind() - + getImp() : BlindingMagicWeaponImpl - + swing() - + unwield() - + wield() - } - abstract class BlindingMagicWeaponImpl { - + BlindingMagicWeaponImpl() - + blindImp() {abstract} - } - class Excalibur { - - LOGGER : Logger {static} - + Excalibur() - + blindImp() - + swingImp() - + unwieldImp() - + wieldImp() - } - class FlyingMagicWeapon { - + FlyingMagicWeapon(imp : FlyingMagicWeaponImpl) - + fly() - + getImp() : FlyingMagicWeaponImpl - + swing() - + unwield() - + wield() - } - abstract class FlyingMagicWeaponImpl { - + FlyingMagicWeaponImpl() - + flyImp() {abstract} - } - abstract class MagicWeapon { - # imp : MagicWeaponImpl - + MagicWeapon(imp : MagicWeaponImpl) - + getImp() : MagicWeaponImpl - + swing() {abstract} - + unwield() {abstract} - + wield() {abstract} - } - abstract class MagicWeaponImpl { - + MagicWeaponImpl() - + swingImp() {abstract} - + unwieldImp() {abstract} - + wieldImp() {abstract} - } - class Mjollnir { - - LOGGER : Logger {static} - + Mjollnir() - + flyImp() - + swingImp() - + unwieldImp() - + wieldImp() - } - class SoulEatingMagicWeapon { - + SoulEatingMagicWeapon(imp : SoulEatingMagicWeaponImpl) - + eatSoul() - + getImp() : SoulEatingMagicWeaponImpl - + swing() - + unwield() - + wield() - } - abstract class SoulEatingMagicWeaponImpl { - + SoulEatingMagicWeaponImpl() - + eatSoulImp() {abstract} - } - class Stormbringer { - - LOGGER : Logger {static} - + Stormbringer() - + eatSoulImp() - + swingImp() - + unwieldImp() - + wieldImp() - } -} -MagicWeapon --> "-imp" MagicWeaponImpl -BlindingMagicWeapon --|> MagicWeapon -BlindingMagicWeaponImpl --|> MagicWeaponImpl -Excalibur --|> BlindingMagicWeaponImpl -FlyingMagicWeapon --|> MagicWeapon -FlyingMagicWeaponImpl --|> MagicWeaponImpl -Mjollnir --|> FlyingMagicWeaponImpl -SoulEatingMagicWeapon --|> MagicWeapon -SoulEatingMagicWeaponImpl --|> MagicWeaponImpl -Stormbringer --|> SoulEatingMagicWeaponImpl -@enduml \ No newline at end of file diff --git a/bridge/src/main/java/com/iluwatar/bridge/App.java b/bridge/src/main/java/com/iluwatar/bridge/App.java index 4fc336042..c986de656 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/App.java +++ b/bridge/src/main/java/com/iluwatar/bridge/App.java @@ -22,40 +22,42 @@ */ package com.iluwatar.bridge; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * - * The Bridge pattern can also be thought of as two layers of abstraction. With Bridge, you can - * decouple an abstraction from its implementation so that the two can vary independently. + * Composition over inheritance. The Bridge pattern can also be thought of as two layers of abstraction. + * With Bridge, you can decouple an abstraction from its implementation so that the two can vary independently. *

- * In Bridge pattern both abstraction ({@link MagicWeapon}) and implementation ( - * {@link MagicWeaponImpl}) have their own class hierarchies. The interface of the implementations + * In Bridge pattern both abstraction ({@link Weapon}) and implementation ( + * {@link Enchantment}) have their own class hierarchies. The interface of the implementations * can be changed without affecting the clients. + *

+ * In this example we have two class hierarchies. One of weapons and another one of enchantments. We can easily + * combine any weapon with any enchantment using composition instead of creating deep class hierarchy. * */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * * @param args command line args */ public static void main(String[] args) { - BlindingMagicWeapon blindingMagicWeapon = new BlindingMagicWeapon(new Excalibur()); - blindingMagicWeapon.wield(); - blindingMagicWeapon.blind(); - blindingMagicWeapon.swing(); - blindingMagicWeapon.unwield(); + LOGGER.info("The knight receives an enchanted sword."); + Sword enchantedSword = new Sword(new SoulEatingEnchantment()); + enchantedSword.wield(); + enchantedSword.swing(); + enchantedSword.unwield(); - FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(new Mjollnir()); - flyingMagicWeapon.wield(); - flyingMagicWeapon.fly(); - flyingMagicWeapon.swing(); - flyingMagicWeapon.unwield(); - - SoulEatingMagicWeapon soulEatingMagicWeapon = new SoulEatingMagicWeapon(new Stormbringer()); - soulEatingMagicWeapon.wield(); - soulEatingMagicWeapon.swing(); - soulEatingMagicWeapon.eatSoul(); - soulEatingMagicWeapon.unwield(); + LOGGER.info("The valkyrie receives an enchanted hammer."); + Hammer hammer = new Hammer(new FlyingEnchantment()); + hammer.wield(); + hammer.swing(); + hammer.unwield(); } } diff --git a/bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeapon.java b/bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeapon.java deleted file mode 100644 index e70cbb96e..000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeapon.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * 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. - */ -package com.iluwatar.bridge; - -/** - * - * BlindingMagicWeapon - * - */ -public class BlindingMagicWeapon extends MagicWeapon { - - public BlindingMagicWeapon(BlindingMagicWeaponImpl imp) { - super(imp); - } - - @Override - public BlindingMagicWeaponImpl getImp() { - return (BlindingMagicWeaponImpl) imp; - } - - @Override - public void wield() { - getImp().wieldImp(); - } - - @Override - public void swing() { - getImp().swingImp(); - } - - @Override - public void unwield() { - getImp().unwieldImp(); - } - - public void blind() { - getImp().blindImp(); - } -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/FlyingMagicWeaponImpl.java b/bridge/src/main/java/com/iluwatar/bridge/Enchantment.java similarity index 90% rename from bridge/src/main/java/com/iluwatar/bridge/FlyingMagicWeaponImpl.java rename to bridge/src/main/java/com/iluwatar/bridge/Enchantment.java index c7b47e780..dd0c17205 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/FlyingMagicWeaponImpl.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Enchantment.java @@ -24,11 +24,14 @@ package com.iluwatar.bridge; /** * - * FlyingMagicWeaponImpl - * + * Enchantment + * */ -public abstract class FlyingMagicWeaponImpl extends MagicWeaponImpl { +public interface Enchantment { - public abstract void flyImp(); + void onActivate(); + void apply(); + + void onDeactivate(); } diff --git a/bridge/src/main/java/com/iluwatar/bridge/Excalibur.java b/bridge/src/main/java/com/iluwatar/bridge/FlyingEnchantment.java similarity index 73% rename from bridge/src/main/java/com/iluwatar/bridge/Excalibur.java rename to bridge/src/main/java/com/iluwatar/bridge/FlyingEnchantment.java index ddd2ac540..8b12c6114 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/Excalibur.java +++ b/bridge/src/main/java/com/iluwatar/bridge/FlyingEnchantment.java @@ -27,30 +27,25 @@ import org.slf4j.LoggerFactory; /** * - * Excalibur + * FlyingEnchantment * */ -public class Excalibur extends BlindingMagicWeaponImpl { +public class FlyingEnchantment implements Enchantment { - private static final Logger LOGGER = LoggerFactory.getLogger(Excalibur.class); + private static final Logger LOGGER = LoggerFactory.getLogger(FlyingEnchantment.class); @Override - public void wieldImp() { - LOGGER.info("wielding Excalibur"); + public void onActivate() { + LOGGER.info("The item begins to glow faintly."); } @Override - public void swingImp() { - LOGGER.info("swinging Excalibur"); + public void apply() { + LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand."); } @Override - public void unwieldImp() { - LOGGER.info("unwielding Excalibur"); - } - - @Override - public void blindImp() { - LOGGER.info("bright light streams from Excalibur blinding the enemy"); + public void onDeactivate() { + LOGGER.info("The item's glow fades."); } } diff --git a/bridge/src/main/java/com/iluwatar/bridge/FlyingMagicWeapon.java b/bridge/src/main/java/com/iluwatar/bridge/Hammer.java similarity index 71% rename from bridge/src/main/java/com/iluwatar/bridge/FlyingMagicWeapon.java rename to bridge/src/main/java/com/iluwatar/bridge/Hammer.java index 85532d410..557ef6691 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/FlyingMagicWeapon.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Hammer.java @@ -22,38 +22,39 @@ */ package com.iluwatar.bridge; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * - * FlyingMagicWeapon + * Hammer * */ -public class FlyingMagicWeapon extends MagicWeapon { +public class Hammer implements Weapon { - public FlyingMagicWeapon(FlyingMagicWeaponImpl imp) { - super(imp); - } + private static final Logger LOGGER = LoggerFactory.getLogger(Hammer.class); - public FlyingMagicWeaponImpl getImp() { - return (FlyingMagicWeaponImpl) imp; + private final Enchantment enchantment; + + public Hammer(Enchantment enchantment) { + this.enchantment = enchantment; } @Override public void wield() { - getImp().wieldImp(); + LOGGER.info("The hammer is wielded."); + enchantment.onActivate(); } @Override public void swing() { - getImp().swingImp(); + LOGGER.info("The hammer is swinged."); + enchantment.apply(); } @Override public void unwield() { - getImp().unwieldImp(); + LOGGER.info("The hammer is unwielded."); + enchantment.onDeactivate(); } - - public void fly() { - getImp().flyImp(); - } - } diff --git a/bridge/src/main/java/com/iluwatar/bridge/MagicWeapon.java b/bridge/src/main/java/com/iluwatar/bridge/MagicWeapon.java deleted file mode 100644 index 049133d91..000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/MagicWeapon.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * 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. - */ -package com.iluwatar.bridge; - -/** - * - * MagicWeapon - * - */ -public abstract class MagicWeapon { - - protected MagicWeaponImpl imp; - - public MagicWeapon(MagicWeaponImpl imp) { - this.imp = imp; - } - - public abstract void wield(); - - public abstract void swing(); - - public abstract void unwield(); - - public MagicWeaponImpl getImp() { - return imp; - } -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/MagicWeaponImpl.java b/bridge/src/main/java/com/iluwatar/bridge/MagicWeaponImpl.java deleted file mode 100644 index b0d3070c1..000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/MagicWeaponImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * 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. - */ -package com.iluwatar.bridge; - -/** - * - * MagicWeaponImpl - * - */ -public abstract class MagicWeaponImpl { - - public abstract void wieldImp(); - - public abstract void swingImp(); - - public abstract void unwieldImp(); - -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java b/bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java deleted file mode 100644 index 7cec530eb..000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * 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. - */ -package com.iluwatar.bridge; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Mjollnir - * - */ -public class Mjollnir extends FlyingMagicWeaponImpl { - - private static final Logger LOGGER = LoggerFactory.getLogger(Mjollnir.class); - - @Override - public void wieldImp() { - LOGGER.info("wielding Mjollnir"); - } - - @Override - public void swingImp() { - LOGGER.info("swinging Mjollnir"); - } - - @Override - public void unwieldImp() { - LOGGER.info("unwielding Mjollnir"); - } - - @Override - public void flyImp() { - LOGGER.info("Mjollnir hits the enemy in the air and returns back to the owner's hand"); - } -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/Stormbringer.java b/bridge/src/main/java/com/iluwatar/bridge/SoulEatingEnchantment.java similarity index 76% rename from bridge/src/main/java/com/iluwatar/bridge/Stormbringer.java rename to bridge/src/main/java/com/iluwatar/bridge/SoulEatingEnchantment.java index 0c7a6ce6b..8b08d155c 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/Stormbringer.java +++ b/bridge/src/main/java/com/iluwatar/bridge/SoulEatingEnchantment.java @@ -27,30 +27,25 @@ import org.slf4j.LoggerFactory; /** * - * Stormbringer + * SoulEatingEnchantment * */ -public class Stormbringer extends SoulEatingMagicWeaponImpl { +public class SoulEatingEnchantment implements Enchantment { - private static final Logger LOGGER = LoggerFactory.getLogger(Stormbringer.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SoulEatingEnchantment.class); @Override - public void wieldImp() { - LOGGER.info("wielding Stormbringer"); + public void onActivate() { + LOGGER.info("The item spreads bloodlust."); } @Override - public void swingImp() { - LOGGER.info("swinging Stormbringer"); + public void apply() { + LOGGER.info("The item eats the soul of enemies."); } @Override - public void unwieldImp() { - LOGGER.info("unwielding Stormbringer"); - } - - @Override - public void eatSoulImp() { - LOGGER.info("Stormbringer devours the enemy's soul"); + public void onDeactivate() { + LOGGER.info("Bloodlust slowly disappears."); } } diff --git a/bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeaponImpl.java b/bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeaponImpl.java deleted file mode 100644 index 2ed27242a..000000000 --- a/bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeaponImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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. - */ -package com.iluwatar.bridge; - -/** - * - * SoulEatingMagicWeaponImpl - * - */ -public abstract class SoulEatingMagicWeaponImpl extends MagicWeaponImpl { - - public abstract void eatSoulImp(); - -} diff --git a/bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeapon.java b/bridge/src/main/java/com/iluwatar/bridge/Sword.java similarity index 71% rename from bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeapon.java rename to bridge/src/main/java/com/iluwatar/bridge/Sword.java index 927ac2d66..73463b1f8 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/SoulEatingMagicWeapon.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Sword.java @@ -22,39 +22,39 @@ */ package com.iluwatar.bridge; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * - * SoulEatingMagicWeapon + * Sword * */ -public class SoulEatingMagicWeapon extends MagicWeapon { +public class Sword implements Weapon { - public SoulEatingMagicWeapon(SoulEatingMagicWeaponImpl imp) { - super(imp); - } + private static final Logger LOGGER = LoggerFactory.getLogger(Sword.class); - @Override - public SoulEatingMagicWeaponImpl getImp() { - return (SoulEatingMagicWeaponImpl) imp; + private final Enchantment enchantment; + + public Sword(Enchantment enchantment) { + this.enchantment = enchantment; } @Override public void wield() { - getImp().wieldImp(); + LOGGER.info("The sword is wielded."); + enchantment.onActivate(); } @Override public void swing() { - getImp().swingImp(); + LOGGER.info("The sword is swinged."); + enchantment.apply(); } @Override public void unwield() { - getImp().unwieldImp(); + LOGGER.info("The sword is unwielded."); + enchantment.onDeactivate(); } - - public void eatSoul() { - getImp().eatSoulImp(); - } - } diff --git a/bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeaponImpl.java b/bridge/src/main/java/com/iluwatar/bridge/Weapon.java similarity index 89% rename from bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeaponImpl.java rename to bridge/src/main/java/com/iluwatar/bridge/Weapon.java index 0bd7d7b52..9bdd715a1 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/BlindingMagicWeaponImpl.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Weapon.java @@ -24,11 +24,14 @@ package com.iluwatar.bridge; /** * - * BlindingMagicWeaponImpl - * + * Weapon + * */ -public abstract class BlindingMagicWeaponImpl extends MagicWeaponImpl { +public interface Weapon { - public abstract void blindImp(); + void wield(); + void swing(); + + void unwield(); } diff --git a/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java index 97298a161..295641a10 100644 --- a/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java +++ b/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java @@ -42,14 +42,14 @@ public class BlindingMagicWeaponTest extends MagicWeaponTest { */ @Test public void testExcalibur() throws Exception { - final Excalibur excalibur = spy(new Excalibur()); - final BlindingMagicWeapon blindingMagicWeapon = new BlindingMagicWeapon(excalibur); - - testBasicWeaponActions(blindingMagicWeapon, excalibur); - - blindingMagicWeapon.blind(); - verify(excalibur, times(1)).blindImp(); - verifyNoMoreInteractions(excalibur); +// final Excalibur excalibur = spy(new Excalibur()); +// final Hammer blindingMagicWeapon = new Hammer(excalibur); +// +// testBasicWeaponActions(blindingMagicWeapon, excalibur); +// +// blindingMagicWeapon.blind(); +// verify(excalibur, times(1)).blindImp(); +// verifyNoMoreInteractions(excalibur); } } diff --git a/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java index fca3ea9ab..76bb77047 100644 --- a/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java +++ b/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java @@ -42,14 +42,14 @@ public class FlyingMagicWeaponTest extends MagicWeaponTest { */ @Test public void testMjollnir() throws Exception { - final Mjollnir mjollnir = spy(new Mjollnir()); - final FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(mjollnir); - - testBasicWeaponActions(flyingMagicWeapon, mjollnir); - - flyingMagicWeapon.fly(); - verify(mjollnir, times(1)).flyImp(); - verifyNoMoreInteractions(mjollnir); +// final Mjollnir mjollnir = spy(new Mjollnir()); +// final FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(mjollnir); +// +// testBasicWeaponActions(flyingMagicWeapon, mjollnir); +// +// flyingMagicWeapon.fly(); +// verify(mjollnir, times(1)).flyImp(); +// verifyNoMoreInteractions(mjollnir); } } \ No newline at end of file diff --git a/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java index e883f03d3..901880cc1 100644 --- a/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java +++ b/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java @@ -41,24 +41,24 @@ public abstract class MagicWeaponTest { * @param weaponImpl The spied weapon implementation where actions are bridged to * @param weapon The weapon, handled by the app */ - protected final void testBasicWeaponActions(final MagicWeapon weapon, - final MagicWeaponImpl weaponImpl) { - assertNotNull(weapon); - assertNotNull(weaponImpl); - assertNotNull(weapon.getImp()); - - weapon.swing(); - verify(weaponImpl, times(1)).swingImp(); - verifyNoMoreInteractions(weaponImpl); - - weapon.wield(); - verify(weaponImpl, times(1)).wieldImp(); - verifyNoMoreInteractions(weaponImpl); - - weapon.unwield(); - verify(weaponImpl, times(1)).unwieldImp(); - verifyNoMoreInteractions(weaponImpl); - + protected final void testBasicWeaponActions(final Weapon weapon, + final Enchantment weaponImpl) { +// assertNotNull(weapon); +// assertNotNull(weaponImpl); +// assertNotNull(weapon.getEnchantment()); +// +// weapon.swing(); +// verify(weaponImpl, times(1)).swingImp(); +// verifyNoMoreInteractions(weaponImpl); +// +// weapon.wield(); +// verify(weaponImpl, times(1)).wieldImp(); +// verifyNoMoreInteractions(weaponImpl); +// +// weapon.unwield(); +// verify(weaponImpl, times(1)).unwieldImp(); +// verifyNoMoreInteractions(weaponImpl); +// } } diff --git a/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java index b71fe2228..e3c5669ed 100644 --- a/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java +++ b/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java @@ -42,14 +42,14 @@ public class SoulEatingMagicWeaponTest extends MagicWeaponTest { */ @Test public void testStormBringer() throws Exception { - final Stormbringer stormbringer = spy(new Stormbringer()); - final SoulEatingMagicWeapon soulEatingMagicWeapon = new SoulEatingMagicWeapon(stormbringer); - - testBasicWeaponActions(soulEatingMagicWeapon, stormbringer); - - soulEatingMagicWeapon.eatSoul(); - verify(stormbringer, times(1)).eatSoulImp(); - verifyNoMoreInteractions(stormbringer); +// final Stormbringer stormbringer = spy(new Stormbringer()); +// final Sword soulEatingMagicWeapon = new Sword(stormbringer); +// +// testBasicWeaponActions(soulEatingMagicWeapon, stormbringer); +// +// soulEatingMagicWeapon.eatSoul(); +// verify(stormbringer, times(1)).eatSoulImp(); +// verifyNoMoreInteractions(stormbringer); } } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 347a6bc15..06148064f 100644 --- a/pom.xml +++ b/pom.xml @@ -467,6 +467,7 @@ builder prototype adapter + bridge From 6f1736d2e6421241e3e15ba764c3e5303962b6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Tue, 22 Aug 2017 22:01:52 +0300 Subject: [PATCH 2/3] Refactored tests for Bridge --- .../main/java/com/iluwatar/bridge/Hammer.java | 5 ++ .../main/java/com/iluwatar/bridge/Sword.java | 5 ++ .../main/java/com/iluwatar/bridge/Weapon.java | 2 + ...ngMagicWeaponTest.java => HammerTest.java} | 22 ++------ .../bridge/SoulEatingMagicWeaponTest.java | 55 ------------------- ...ingMagicWeaponTest.java => SwordTest.java} | 24 +++----- .../{MagicWeaponTest.java => WeaponTest.java} | 47 +++++++--------- 7 files changed, 46 insertions(+), 114 deletions(-) rename bridge/src/test/java/com/iluwatar/bridge/{FlyingMagicWeaponTest.java => HammerTest.java} (69%) delete mode 100644 bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java rename bridge/src/test/java/com/iluwatar/bridge/{BlindingMagicWeaponTest.java => SwordTest.java} (69%) rename bridge/src/test/java/com/iluwatar/bridge/{MagicWeaponTest.java => WeaponTest.java} (65%) diff --git a/bridge/src/main/java/com/iluwatar/bridge/Hammer.java b/bridge/src/main/java/com/iluwatar/bridge/Hammer.java index 557ef6691..51bfda2a1 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/Hammer.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Hammer.java @@ -57,4 +57,9 @@ public class Hammer implements Weapon { LOGGER.info("The hammer is unwielded."); enchantment.onDeactivate(); } + + @Override + public Enchantment getEnchantment() { + return enchantment; + } } diff --git a/bridge/src/main/java/com/iluwatar/bridge/Sword.java b/bridge/src/main/java/com/iluwatar/bridge/Sword.java index 73463b1f8..6f52943a6 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/Sword.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Sword.java @@ -57,4 +57,9 @@ public class Sword implements Weapon { LOGGER.info("The sword is unwielded."); enchantment.onDeactivate(); } + + @Override + public Enchantment getEnchantment() { + return enchantment; + } } diff --git a/bridge/src/main/java/com/iluwatar/bridge/Weapon.java b/bridge/src/main/java/com/iluwatar/bridge/Weapon.java index 9bdd715a1..a2d21b88f 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/Weapon.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Weapon.java @@ -34,4 +34,6 @@ public interface Weapon { void swing(); void unwield(); + + Enchantment getEnchantment(); } diff --git a/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/HammerTest.java similarity index 69% rename from bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java rename to bridge/src/test/java/com/iluwatar/bridge/HammerTest.java index 76bb77047..a650bae04 100644 --- a/bridge/src/test/java/com/iluwatar/bridge/FlyingMagicWeaponTest.java +++ b/bridge/src/test/java/com/iluwatar/bridge/HammerTest.java @@ -24,32 +24,22 @@ package com.iluwatar.bridge; import org.junit.Test; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.internal.verification.VerificationModeFactory.times; /** - * Date: 12/6/15 - 11:26 PM - * - * @author Jeroen Meulemeester + * Tests for hammer */ -public class FlyingMagicWeaponTest extends MagicWeaponTest { +public class HammerTest extends WeaponTest { /** * Invoke all possible actions on the weapon and check if the actions are executed on the actual * underlying weapon implementation. */ @Test - public void testMjollnir() throws Exception { -// final Mjollnir mjollnir = spy(new Mjollnir()); -// final FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(mjollnir); -// -// testBasicWeaponActions(flyingMagicWeapon, mjollnir); -// -// flyingMagicWeapon.fly(); -// verify(mjollnir, times(1)).flyImp(); -// verifyNoMoreInteractions(mjollnir); + public void testHammer() throws Exception { + final Hammer hammer = spy(new Hammer(mock(FlyingEnchantment.class))); + testBasicWeaponActions(hammer); } - } \ No newline at end of file diff --git a/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java deleted file mode 100644 index e3c5669ed..000000000 --- a/bridge/src/test/java/com/iluwatar/bridge/SoulEatingMagicWeaponTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * 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. - */ -package com.iluwatar.bridge; - -import org.junit.Test; - -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.internal.verification.VerificationModeFactory.times; - -/** - * Date: 12/6/15 - 11:43 PM - * - * @author Jeroen Meulemeester - */ -public class SoulEatingMagicWeaponTest extends MagicWeaponTest { - - /** - * Invoke all possible actions on the weapon and check if the actions are executed on the actual - * underlying weapon implementation. - */ - @Test - public void testStormBringer() throws Exception { -// final Stormbringer stormbringer = spy(new Stormbringer()); -// final Sword soulEatingMagicWeapon = new Sword(stormbringer); -// -// testBasicWeaponActions(soulEatingMagicWeapon, stormbringer); -// -// soulEatingMagicWeapon.eatSoul(); -// verify(stormbringer, times(1)).eatSoulImp(); -// verifyNoMoreInteractions(stormbringer); - } - -} \ No newline at end of file diff --git a/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/SwordTest.java similarity index 69% rename from bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java rename to bridge/src/test/java/com/iluwatar/bridge/SwordTest.java index 295641a10..7ffd0e492 100644 --- a/bridge/src/test/java/com/iluwatar/bridge/BlindingMagicWeaponTest.java +++ b/bridge/src/test/java/com/iluwatar/bridge/SwordTest.java @@ -24,32 +24,22 @@ package com.iluwatar.bridge; import org.junit.Test; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.internal.verification.VerificationModeFactory.times; /** - * Date: 12/6/15 - 11:15 PM - * - * @author Jeroen Meulemeester + * Tests for sword */ -public class BlindingMagicWeaponTest extends MagicWeaponTest { +public class SwordTest extends WeaponTest { /** * Invoke all possible actions on the weapon and check if the actions are executed on the actual * underlying weapon implementation. */ @Test - public void testExcalibur() throws Exception { -// final Excalibur excalibur = spy(new Excalibur()); -// final Hammer blindingMagicWeapon = new Hammer(excalibur); -// -// testBasicWeaponActions(blindingMagicWeapon, excalibur); -// -// blindingMagicWeapon.blind(); -// verify(excalibur, times(1)).blindImp(); -// verifyNoMoreInteractions(excalibur); + public void testSword() throws Exception { + final Sword sword = spy(new Sword(mock(FlyingEnchantment.class))); + testBasicWeaponActions(sword); } - -} +} \ No newline at end of file diff --git a/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java similarity index 65% rename from bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java rename to bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java index 901880cc1..daec1014a 100644 --- a/bridge/src/test/java/com/iluwatar/bridge/MagicWeaponTest.java +++ b/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java @@ -28,37 +28,32 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.internal.verification.VerificationModeFactory.times; /** - * Date: 12/6/15 - 11:28 PM - * - * @author Jeroen Meulemeester + * Base class for weapon tests */ -public abstract class MagicWeaponTest { +public abstract class WeaponTest { /** - * Invoke the basic actions of the given weapon, and test if the underlying weapon implementation + * Invoke the basic actions of the given weapon, and test if the underlying enchantment implementation * is invoked * - * @param weaponImpl The spied weapon implementation where actions are bridged to - * @param weapon The weapon, handled by the app */ - protected final void testBasicWeaponActions(final Weapon weapon, - final Enchantment weaponImpl) { -// assertNotNull(weapon); -// assertNotNull(weaponImpl); -// assertNotNull(weapon.getEnchantment()); -// -// weapon.swing(); -// verify(weaponImpl, times(1)).swingImp(); -// verifyNoMoreInteractions(weaponImpl); -// -// weapon.wield(); -// verify(weaponImpl, times(1)).wieldImp(); -// verifyNoMoreInteractions(weaponImpl); -// -// weapon.unwield(); -// verify(weaponImpl, times(1)).unwieldImp(); -// verifyNoMoreInteractions(weaponImpl); -// - } + protected final void testBasicWeaponActions(final Weapon weapon) { + assertNotNull(weapon); + Enchantment enchantment = weapon.getEnchantment(); + assertNotNull(enchantment); + assertNotNull(weapon.getEnchantment()); + weapon.swing(); + verify(enchantment, times(1)).apply(); + verifyNoMoreInteractions(enchantment); + + weapon.wield(); + verify(enchantment, times(1)).onActivate(); + verifyNoMoreInteractions(enchantment); + + weapon.unwield(); + verify(enchantment, times(1)).onDeactivate(); + verifyNoMoreInteractions(enchantment); + + } } From 1dc038bc30798d849a127d5bbec62dffc32baebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Wed, 23 Aug 2017 21:25:48 +0300 Subject: [PATCH 3/3] Add explanation for Bridge pattern --- bridge/README.md | 166 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 3 deletions(-) diff --git a/bridge/README.md b/bridge/README.md index 6c1e70631..a37c35174 100644 --- a/bridge/README.md +++ b/bridge/README.md @@ -15,10 +15,170 @@ tags: Handle/Body ## Intent -Decouple an abstraction from its implementation so that the two can -vary independently. +Decouple an abstraction from its implementation so that the two can vary independently. -![alt text](./etc/bridge.png "Bridge") +## Explanation + +Real world example + +> Consider you have a weapon with different enchantments and you are supposed to allow mixing different weapons with different enchantments. What would you do? Create multiple copies of each of the weapons for each of the enchantments or would you just create separate enchantment and set it for the weapon as needed? Bridge pattern allows you to do the second. + +In Plain Words + +> Bridge pattern is about preferring composition over inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy. + +Wikipedia says + +> The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently" + +**Programmatic Example** + +Translating our weapon example from above. Here we have the `Weapon` hierarchy + +``` +public interface Weapon { + void wield(); + void swing(); + void unwield(); + Enchantment getEnchantment(); +} + +public class Sword implements Weapon { + + private final Enchantment enchantment; + + public Sword(Enchantment enchantment) { + this.enchantment = enchantment; + } + + @Override + public void wield() { + LOGGER.info("The sword is wielded."); + enchantment.onActivate(); + } + + @Override + public void swing() { + LOGGER.info("The sword is swinged."); + enchantment.apply(); + } + + @Override + public void unwield() { + LOGGER.info("The sword is unwielded."); + enchantment.onDeactivate(); + } + + @Override + public Enchantment getEnchantment() { + return enchantment; + } +} + +public class Hammer implements Weapon { + + private final Enchantment enchantment; + + public Hammer(Enchantment enchantment) { + this.enchantment = enchantment; + } + + @Override + public void wield() { + LOGGER.info("The hammer is wielded."); + enchantment.onActivate(); + } + + @Override + public void swing() { + LOGGER.info("The hammer is swinged."); + enchantment.apply(); + } + + @Override + public void unwield() { + LOGGER.info("The hammer is unwielded."); + enchantment.onDeactivate(); + } + + @Override + public Enchantment getEnchantment() { + return enchantment; + } +} +``` + +And the separate enchantment hierarchy + +``` +public interface Enchantment { + void onActivate(); + void apply(); + void onDeactivate(); +} + +public class FlyingEnchantment implements Enchantment { + + @Override + public void onActivate() { + LOGGER.info("The item begins to glow faintly."); + } + + @Override + public void apply() { + LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand."); + } + + @Override + public void onDeactivate() { + LOGGER.info("The item's glow fades."); + } +} + +public class SoulEatingEnchantment implements Enchantment { + + @Override + public void onActivate() { + LOGGER.info("The item spreads bloodlust."); + } + + @Override + public void apply() { + LOGGER.info("The item eats the soul of enemies."); + } + + @Override + public void onDeactivate() { + LOGGER.info("Bloodlust slowly disappears."); + } +} +``` + +And both the hierarchies in action + +``` +Sword enchantedSword = new Sword(new SoulEatingEnchantment()); +enchantedSword.wield(); +enchantedSword.swing(); +enchantedSword.unwield(); +// The sword is wielded. +// The item spreads bloodlust. +// The sword is swinged. +// The item eats the soul of enemies. +// The sword is unwielded. +// Bloodlust slowly disappears. + +Hammer hammer = new Hammer(new FlyingEnchantment()); +hammer.wield(); +hammer.swing(); +hammer.unwield(); +// The hammer is wielded. +// The item begins to glow faintly. +// The hammer is swinged. +// The item flies and strikes the enemies finally returning to owner's hand. +// The hammer is unwielded. +// The item's glow fades. +``` ## Applicability Use the Bridge pattern when