設計模式系列之「裝飾模式」

**小Y:**Hello,你們好,歡迎來到魂鬥羅.歸來的世界,下面讓小Y帶領你們一塊兒去採訪一下叼煙大漢比爾·雷澤,讓你們更加理解這個粗狂的戰鬥漢子。Let's go。!ide

**小Y:**你最喜歡幹什麼?學習

**比爾·雷澤:**最喜歡衝關打爆大機。this

**小Y:**比爾,你想對觀衆說些什麼?spa

**比爾·雷澤:**想挑戰我,隨時奉陪!一顆不夠,給你來三顆!設計

小Y:......3d

比爾·雷澤做爲魂鬥羅這麼經典的人物,原來也是一個粗狂耿直boy呀。爲了保存住他的光輝形象和讓你們更加了解他,小Y決定把比爾·雷澤的攻擊技能裝飾一番介紹給你們認識。代理

1、案例設想

**比爾·雷澤在戰場上在戰場上基本上用散彈槍能夠橫掃小兵,可是遇到一些特殊的狀況仍是須要經過G5手雷、集速手雷、爆破飛彈等技能來進行輔助。**那麼如何設置這些技能才合適呢?簡單,小Y腦海中立馬閃過幾種方案:調試

(1)採用繼承的方式,設定一個比爾·雷澤類,有多少個技能就寫多少個子類來繼承這個比爾·雷澤類。 code

看完這個圖,小Y本身都蒙逼了,每增長一個技能能夠組合出N個子類,這只是一個比爾·雷澤,再來個艾薇、寒鋒什麼的,那不就要加到天荒地老?cdn

(2)直接抽象一個角色類,裏面包含了每一個角色的技能。

這樣子有多少個角色就增長多少個子類就能夠了,不用根據技能增長類,避免形成子類爆炸,可是,每一個角色的技能是能夠疊加使用的,角色越多或者技能疊加種類越多,那麼就要在超類增長越多的方法,並且直接修改超類不符合開閉原則(超類對擴展開放,對修改關閉)。

(3)今天的主題— 裝飾模式。

2、裝飾模式的概念

1.裝飾模式定義

裝飾模式(Decorator Pattern)是一種比較常見的模式,動態地給一個對象添加一些額外的職責(就增長功能來講,裝飾模式相比生成子類更爲靈活)。

2.使用的場景

  • 須要擴展一個類的功能,或者給一個類添加附加職責(即核心功能不變,對其進行擴展)。
  • 須要增長由一些基本功能的排列組合而產生的很是大量的功能,從而使繼承關係變的不現實,使得子類數目呈爆炸性增加。

3.角色介紹

  • Component抽象構件

    Component是一個接口或者是抽象類,就是定義咱們最核心的對象,也就是最原始的對象(在裝飾模式中,必然有一個最基本、最核心、最原始的接口或抽象類充當Component抽象構件) 。

  • ConcreteState具體狀態角色

    ConcreteComponent 具體構件,是Component的具體實現,要裝飾的就是它 。

  • Decorator裝飾角色

    通常是一個抽象類,實現Component接口或者抽象方法,它裏面可不必定有抽象的方法呀,在它的屬性裏必然有一個private變量指向Component抽象構件(若是具體裝飾角色只有一個,這個能夠省略)。

  • ConcreteDecorator具體裝飾角色

    把你最核心的、最原始的、最基本的東西裝飾成想要的東西。

4.案例實現

(1)裝飾模式實現角色裝飾UML圖

①抽象角色類

public abstract class Character {
	public abstract void attack();
} 
複製代碼

②實現角色比爾·雷澤(對它進行裝飾)

public class BillRizer extends Character {
	@Override
	public void attack() {
		//角色最基本的技能
		System.out.print("散彈槍進行掃射!");
	}
}
複製代碼

③技能裝飾抽象類

public abstract class SkillDecorator extends Character{
	private Character character;

	public SkillDecorator(Character character) {
		this.character = character;
	}

	@Override
	public void attack() {
		this.character.attack();
	}
}
複製代碼

④G5手雷技能

public class G5GrenadeDecorator extends SkillDecorator {
	public G5GrenadeDecorator(Character character) {
		super(character);
	}

	@Override
	public void attack() {
		super.attack();
		System.out.print("G5手雷輔助攻擊!");
	}
}
複製代碼

⑤集速手雷技能

public class SetspeedDecorator extends SkillDecorator {
	public SetspeedDecorator(Character character) {
		super(character);
	}

	@Override
	public void attack() {
		super.attack();
		System.out.print("集速手雷輔助!");
	}
}
複製代碼

⑥爆破飛彈技能

public class ExplosiveMissileDecorator extends SkillDecorator {
	public ExplosiveMissileDecorator(Character character) {
		super(character);
	}

	@Override
	public void attack() {
		super.attack();
		System.out.print("爆破飛彈輔助!");
	}
}
複製代碼

⑦客戶端

public class Client {
	public static void main(String[] args){
		//須要裝飾的BillRizer
		BillRizer billRizer=new BillRizer();
		//使用G5手雷輔助
		G5GrenadeDecorator g5GrenadeDecorator=new G5GrenadeDecorator(billRizer);
		g5GrenadeDecorator.attack();
	
		//使用G5手雷+集速手雷+爆破飛彈輔助
		SetspeedDecorator setspeedDecorator=new SetspeedDecorator(g5GrenadeDecorator);
		ExplosiveMissileDecorator explosiveMissileDecorator=new ExplosiveMissileDecorator(setspeedDecorator);
		explosiveMissileDecorator.attack();
	}
}
複製代碼

輸出結果:

①散彈槍進行掃射!G5手雷輔助攻擊!
②散彈槍進行掃射!G5手雷輔助攻擊!集速手雷輔助!爆破飛彈輔助!
複製代碼

把比爾·雷澤的技能介紹一番,你們會發現原來這個看似粗狂的大漢真的霸氣十足啊,有資格看你不爽就來一句「想挑戰我,隨時奉陪!一顆不夠,給你來三顆」。

3、總結分析

  • 優勢:
    ①裝飾類和被裝飾類能夠獨立發展,而不會相互耦合。Component類無須知道Decorator類,而Decorator也不用知道具體的構件,用戶能夠根據須要增長新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有代碼無須改變,符合「開閉原則」。 ②裝飾模式是繼承關係的一個替代方案。裝飾模式與繼承關係的目的都是要擴展對象的功能,可是裝飾模式能夠提供比繼承更多的靈活性。 ③經過使用不一樣的具體裝飾類以及這些裝飾類的排列組合,能夠創造出不少不一樣行爲的組合。

  • 缺點:
    ①這種比繼承更加靈活機動的特性,也同時意味着裝飾模式比繼承更加易於出錯,排錯也很困難,對於屢次裝飾的對象,調試時尋找錯誤可能須要逐級排查,較爲煩瑣。 ②使用裝飾模式進行系統設計時將產生不少小對象,這些裝飾類和小對象的產生將增長系統的複雜度,加大學習與理解的難度。

看到裝飾模式不少小夥伴會發現跟代理模式很類似,下一篇小Y會對這兩種模式進行對比,請期待!!!!

簡書地址:http://www.jianshu.com/p/d7a9208c6829

Android技術交流吧
相關文章
相關標籤/搜索