裝飾(Decorator Pattern)模式
在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。就增加功能來說,裝飾模式比生成子類更爲靈活。
使用場景:
-
需要擴展一個類的功能,或給一個類添加附加職責。
-
需要動態的給一個對象添加功能,這些功能可以再動態的撤銷。
-
需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不現實。
4.當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因爲類定義被隱藏,或類定義不能用於生成子類。
優點:
1.Decorator模式與繼承關係的目的都是要擴展對象的功能,但是Decorator可以提供比繼承更多的靈活性。
- 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行爲的組合。
缺點:
-
這種比繼承更加靈活機動的特性,同時也更加複雜。
-
裝飾模式會導致設計中出現許多小類,如果過度使用,會使程序變得很複雜。
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技術資料,需要的朋友可以在關注後私信我