GoF之裝飾模式遇見王者榮耀、刺激戰場

裝飾(Decorator Pattern)模式

在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。就增加功能來說,裝飾模式比生成子類更爲靈活。

使用場景:

  1. 需要擴展一個類的功能,或給一個類添加附加職責。

  2. 需要動態的給一個對象添加功能,這些功能可以再動態的撤銷。

  3. 需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不現實。

4.當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因爲類定義被隱藏,或類定義不能用於生成子類。

優點:

1.Decorator模式與繼承關係的目的都是要擴展對象的功能,但是Decorator可以提供比繼承更多的靈活性。

  1. 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行爲的組合。

缺點:

  1. 這種比繼承更加靈活機動的特性,同時也更加複雜。

  2. 裝飾模式會導致設計中出現許多小類,如果過度使用,會使程序變得很複雜。

3.裝飾模式是針對抽象組件(Component)類型編程。但是,如果你要針對具體組件編程時,就應該重新思考你的應用架構,以及裝飾者是否合適。當然也可以改變Component接口,增加新的公開的行爲,實現“半透明”的裝飾者模式。在實際項目中要做出最佳選擇。

具體實現:

王者榮耀英雄角色安琪拉,學三個技能,1(Q)、2(W)、3(E)的動態實現。

//Component 英雄接口 
publicinterface Hero {
 //學習技能
 void learnSkills();
}
//ConcreteComponent具體英雄安琪拉,這裏可以用新的英雄實現類來增加新英雄角色
public class Angela implements Hero {
 private String name;
 public Angela(Stringname) {
 this.name = name;
 }
 @Override
 public void learnSkills() {
 System.out.println(name + "學習了以上技能!");
 }
}
 //Decorator 技能池 通過增加英雄實現類,可以增加英雄技能池、皮膚池、武器池等待
 public abstractSkills implements Hero{
 //持有一個英雄對象接口
 private Hero hero;
 public Skills(Herohero) {
 this.hero = hero;
 }
 @Override
 public void learnSkills() {
 if(hero != null)
 hero.learnSkills();
 } 
}
//ConreteDecorator技能:Q 通過增加技能實現類即可增加技能種類
public class Skill_Q extends Skills{
 private String skillName;
 public Skill_Q(Hero hero,String skillName) {
 super(hero);
 this.skillName = skillName;
 }
 @Override
 public voidlearnSkills() {
 System.out.println("學習技能Q:"+skillName);
 super.learnSkills();
 }
}
 //ConreteDecorator 技能:W
 public class Skill_W extends Skills{
 private String skillName;
 public Skill_W(Hero hero,String skillName) {
 super(hero);
 this.skillName = skillName;
 }
 @Override
 public voidlearnSkills() {
 System.out.println("學習技能W:"+ skillName);
 super.learnSkills();
 }
 }
 //ConreteDecorator 技能:E
 public class Skill_E extends Skills{
 private String skillName;
 public Skill_E(Hero hero,StringskillName) {
 super(hero);
 this.skillName =skillName;
 }
 @Override
 public voidlearnSkills() {
 System.out.println("學習技能E:"+skillName);
 super.learnSkills();
 }
 }
 //客戶端:召喚師 
 public class Player {
 public static void main(String[]args) {
 //選擇英雄 有多少英雄接口實現類 就有多少種選擇
 Hero hero = newAngela("安琪拉");
 Skills skills = new Skills(hero);
 //裝扮的順序不限 此爲單獨學習技能
 Skills q = new Skill_Q(skills,"火球術");
 Skillsw = new Skill_W(skills,"混沌火種");
 Skillse = new Skill_E(skills,"制熱光輝");
 //學習技能
 q.learnSkills();
 w.learnSkills();
 e.learnSkills();
 //一整套技能學習
 Skills q = newSkill_Q(skills,"火球術");
 Skills w = newSkill_W(q,"混沌火種");
 Skills e = newSkill_E(w,"制熱光輝");
 e.learnSkills();
 }
}

《刺激戰場》遊戲裏面裝備98K槍械,更換彈夾、倍鏡。
Kar 98K有5發子彈;

裝上彈匣後有10發子彈;

裝上4倍鏡後可以進行4倍瞄準;

裝上8倍鏡後可以進行4倍瞄準、8倍瞄準。

//定義具備射擊功能的槍械接口
public interface Gun {
 //射擊
 publicvoid fire();
}
//創建具體的槍械實現類Kar98K,默認5發子彈
public class Kar98K implements Gun {
 @Override
 publicvoid fire() {
 System.out.println("射擊5次");
 }
}
//對槍械的彈夾進行裝飾,抽象實現槍械接口
public abstract class AbstractMagazine implements Gun{
//持有槍械對象
 private Gun gun;
 public AbstractMagazine(Gun gun) {
 this.gun = gun;
 }
 @Override
 public void fire() {
 gun.fire();
 }
}
//槍械彈夾裝飾的具體實現類,子彈增加至10發
public class Magazine extends AbstractMagazine {
 public Magazine(Gun gun) {
 super(gun);
 }
 @Override
 public void fire() {
 System.out.println("射擊10次");
 }
}
//客戶端
public class Player {
 public static void main(String[] args) {
 //撿起一把98K
 Gun gun = newKar98K();
 //射擊5次
 gun.fire();
 //裝飾上彈匣
 gun = new Magazine(gun);
 //射擊10次
 gun.fire();
 }
 }

現在我要裝上4倍鏡,使它具有4倍瞄準功能,這是槍支原本沒有的功能。

擴展槍支接口功能:

//對槍械接口的繼承,再增加倍鏡裝飾
public interface Aim4X extends Gun {
 public void aim4X();
}
public abstract class AbstractTelescope4X implements Aim4X {
 private Gun gun;
 public AbstractTelescope4X(Gun gun) {
 this.gun = gun;
 }
 @Override
 public void fire() {
 gun.fire();
 }
}
public class Telescope4X extends AbstractTelescope4X {
 public Telescope4X(Gun gun) {
 super(gun);
 }
 @Override
 publicvoid aim4X() {
 System.out.println("已進入4倍瞄準模式");
 }
}
//55式4倍鏡
public class Telescope4X55 extends AbstractTelescope4X {
 public Telescope4X55(Gun gun) {
 super(gun);
 }
 @Override
 publicvoid aim4X() {
 System.out.println("4倍超級瞄準已部署");
 }
 }
 
public class Player {
 public static void main(String[] args) {
 //撿起一把98K
 Gun gun = newKar98K();
 //裝飾上4倍鏡
 Aim4X aim4X = new Telescope4X(gun);
 //4倍瞄準]
 aim4X.aim4X();
 //射擊
 aim4X.fire();
 //先裝飾上彈匣
 gun = new Magazine(gun);
 //再裝飾上4倍鏡
 aim4X = new Telescope4X(gun);
 //4倍瞄準
 aim4X.aim4X();
 //換上55式4倍鏡
 aim4X = new Telescope4X55(gun);
 //射擊!
 aim4X.fire();
 }
 }

現在我要裝上8倍鏡,它具有4倍瞄準功能,也具有8倍瞄準功能。

擴展接口:

public interface Aim8X extends Aim4X {
 public void aim8X();
 }
public abstract class AbstractTelescope8X implements Aim8X {
 private Gun gun;
 public AbstractTelescope8X(Gun gun) {
 this.gun = gun;
 }
 @Override
 public void fire() {
 gun.fire();
 }
 }
public class Telescope8X extends AbstractTelescope8X {
 public Telescope8X(Gun gun) {
 super(gun);
 }
 @Override
 publicvoid aim8X() {
 System.out.println("進入8倍瞄準模式");
 }
 @Override
 publicvoid aim4X() {
 System.out.println("進入4倍瞄準模式");
 }
}
 
public class Player {
 public static void main(String[] args) {
 //先裝飾上彈匣
 gun = new Magazine(gun);
 //再裝飾上8倍鏡
 aim8X = new Telescope8X(gun);
 //8倍瞄準
 aim8X.aim8X();
 //敵人很近,換4倍
 aim8X.aim4X();
 //射擊!
 aim8X.fire();
 }
 }

原文:https://mp.weixin.qq.com/s/hxxNd2QJwKdOecLiDmJCcA

作者:專注一行代碼

來源:微信公衆號

免費分享java技術資料,需要的朋友可以在關注後私信我

在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章