感覺好像用不到的感覺,開始學了設計模式後才發現物件導向 "程式碼再利用" 的精神.
今天來介紹一個會用到 interface、abstract class 的設計模式,策略模式~
先不考慮程式,單純看名字(設計模式的名字很重要),策略 strategy:
什麼是策略? 對我來說策略是 針對同一個問題的不同解決方法
例如 填飽肚子 是你的問題,那 吃飯、吃麵、吃麵包 就個別是你的策略,都是能讓你填飽肚子的食物,就看你選擇哪一個。
[程式示範]
假設現在有一款遊戲,裡面有四個角色,騎士、法師、妖精、王子
(很熟悉?!代表我們同年代 )
以前我在寫都會把 "攻擊行為" 寫在個角色內.
騎士會揮劍
法師會放魔法
妖精會射弓劍
王子會...叫人
轉成Java
// 騎士 public class Knight { // 攻擊 public void Attack(){ System.out.println("揮劍"); } }
// 妖精 public class Elf { // 攻擊 public void Attack(){ System.out.println("射弓劍"); } }
// 王子 public class Prince { // 攻擊 public void Attack(){ System.out.println("叫人..."); } }
// 魔法師 public class Wizard { // 攻擊 public void Attack(){ System.out.println("放魔法"); } }現在你想新增一個角色黑暗妖精,是不是又再多寫一個黑妖的類別,然後再寫他的攻擊方法...如果想增加其他技能,要個別增加,如果角色有100個...這太累人了
這時就是abstract class出場的時候,你可以增加一個角色的抽象類別
// 抽象類別 角色
public abstract class charater { // 一般攻擊 public abstract void attack(); // 技能 public abstract void ability(); // 顯示角色 public abstract void display(); }
再將各個職業角色繼承charater類別,基本上你所有的角色就有這三個方法了.
騎士範例
// 騎士 public class Knight extends Charater { // 一般攻擊 @Override public void attack() { System.out.println("揮劍"); } // 魔法攻擊 @Override public void ability() { System.out.println("放魔法"); } // 顯示角色 @Override public void display() { System.out.println("我是騎士"); } }
現在想新增一個村子裡NPC的角色,NPC不會攻擊也不會放魔法,該怎麼辦呢?
直接空白不寫?那如果有個會攻擊的NPC怎麼辦?
這時可以利用interface,降臨!!!~
宣告兩個interface
- AttackHavior
- MagicAbility
public interface AttackBehavior { void attack(); }
public interface MagicAbility { void magic(); }
實作這兩個攻擊方式的類別
//揮劍攻擊 public class WieldAttack implements AttackBehavior { @Override public void attack() { System.out.println("揮劍"); } }
// 一級魔法 public class LevelOneMagic implements MagicAbility { @Override public void magic() { System.out.println("使用一級魔法"); } }
// 不會物理攻擊 public class AttackNoWay implements AttackBehavior { @Override public void attack() { System.out.println("不會攻擊"); } }
// 不會魔法攻擊 public class MagicNoWay implements MagicAbility { @Override public void magic() { System.out.println("不會放魔法"); } }
再將charater改成
// 抽象類別 角色 public abstract class Charater { // 物理攻擊行為 AttackBehavior attackBehavior; // 魔法攻擊行為 MagicAbility magicAbility; // 一般攻擊 public void attack(){ attackBehavior.attack(); } // 技能 public void ability(){ magicAbility.magic(); } // 顯示角色 public abstract void display(); }
此時的騎士類別變成
// 騎士 public class Knight extends Charater { // 建構子預設攻擊行為 public Knight() { this.attackBehavior = new WieldAttack(); this.magicAbility = new LevelOneMagic(); } // 顯示角色 @Override public void display() { System.out.println("我是騎士"); } }
NPC類別
//NPC public class NPC extends Charater { // 建構子預設攻擊行為 public NPC() { this.attackBehavior = new AttackNoWay(); this.magicAbility = new MagicNoWay(); } // 顯示角色 @Override public void display() { System.out.println("我是NPC"); } }
在主方法執行
Charater knight = new Knight(); knight.display(); knight.attack(); knight.ability(); Charater npc = new NPC(); npc.display(); npc.attack(); npc.ability();便能看到
我是騎士 揮劍 使用一級魔法 我是NPC 不會攻擊 不會放魔法
那如果想動態設定物理攻擊和魔法攻擊呢?
只要在Charater類別上修改成
// 抽象類別 角色 public abstract class Charater { AttackBehavior attackBehavior; MagicAbility magicAbility; // 一般攻擊 public void attack(){ attackBehavior.attack(); } // 技能 public void ability(){ magicAbility.magic(); } // 顯示角色 public abstract void display(); // 設定物理攻擊 public void setAttackBehavior(AttackBehavior attackBehavior){ this.attackBehavior = attackBehavior; } // 設定魔法攻擊 public void setMagicAbility(MagicAbility magicAbility){ this.magicAbility = magicAbility; } }
如此一來 你要增加其他新的攻擊跟魔法就更輕鬆了,物件導向真的很強大!!!
快去試試你的策略模式吧~~
沒有留言:
張貼留言