本文將討論Java設計模式中比較重要的模式之一:裝飾者模式
該系列其他文章:
- 安卓設計模式(一)面向?qū)ο罅笤O計原則
- 安卓設計模式(二)單例模式
- 安卓設計模式(三)Builder模式
- 安卓設計模式(四)裝飾者模式
- 安卓設計模式(五)代理模式
- 安卓設計模式(六)策略模式
- 安卓設計模式(七)模板方法模式
- 安卓設計模式(八)工廠方法模式
裝飾者模式
裝飾者模式也稱為包裝模式,屬于結(jié)構(gòu)型設計模式
定義:動態(tài)地給一個對象添加一些額外的職責.就增加功能來說,裝飾模式相比生成子類更為靈活.
使用場景:需要透明且動態(tài)的地擴展類的功能時.
UML類圖
包括以下幾個角色:
- 抽象構(gòu)件(Component)角色:給出一個抽象接口嗦锐,規(guī)范待裝飾者的功能方法。
- 具體構(gòu)件(ConcreteComponent)角色:待裝飾類。
- 裝飾(Decorator)角色:持有一個構(gòu)件(Component)對象的實例溪北,并定義一個與抽象構(gòu)件接口一致的接口。
- 具體裝飾(ConcreteDecorator)角色:具體裝飾者。
舉例
Component:抽象組件
/**
* =================中康================
*
* @Author: 陳振
* @Email : 18620156376@163.com
* @Time : 2016/11/1 14:36
* @Action :待裝飾者抽象:開發(fā)者
*
* =================中康================
*/
public abstract class Coder {
public abstract void dev();//開發(fā)公司項目
}
ConcreteComponent:具體組件
/**
* =================中康================
*
* @Author: 陳振
* @Email : 18620156376@163.com
* @Time : 2016/11/1 14:38
* @Action :待裝飾者具體實現(xiàn):安卓開發(fā)一枚
*
* =================中康================
*/
public class AndroidCoder extends Coder {
@Override
public void dev() {
Log.i("AndroidCoder", "開發(fā)公司的安卓項目");
}
}
Decorator:裝飾者抽象
/**
* =================中康================
*
* @Author: 陳振
* @Email : 18620156376@163.com
* @Time : 2016/11/1 14:42
* @Action :裝飾者抽閑:具有維護開源項目的增強型功能
*
* =================中康================
*/
public abstract class OpenSource extends Coder {
private Coder mCoder;
public OpenSource(Coder coder) {//注意這里,裝飾者會持有待裝飾者組件的實例
mCoder = coder;
}
public abstract void fixBug();//修復開源項目中的bug
@Override
protected void dev() {
mCoder.dev();
}
}
ConcreteDecorator:具體裝飾者
/**
* =================中康================
*
* @Author: 陳振
* @Email : 18620156376@163.com
* @Time : 2016/11/1 14:44
* @Action :裝飾者,具有修復github上項目的bug的功能
*
* =================中康================
*/
public class GithubFixer extends OpenSource {
public GithubFixer(Coder coder) {
super(coder);
}
@Override
public void fixBug() {
Log.i("GithubFixer", "修復github上的bug");
}
@Override
public void dev() {
fixBug();//上班之前先看看開源項目有沒有bug需要修復
super.dev();//再開始開發(fā)
}
}
實際使用
AndroidCoder androidCoder = new AndroidCoder();//安卓開發(fā)者
androidCoder.dev();//以前每天上班就是寫代碼
//裝飾者模式之后
GithubFixer githubFixer = new GithubFixer(androidCoder);//公司項目沒那么緊,每天開發(fā)之前可以先維護下開源項目
githubFixer.dev();
new GithubFixer(androidCoder).dev();//與以上等價
結(jié)果:
AndroidCoder: 修復github上的bug
GithubFixer:開發(fā)公司的安卓項目
分析
在這個例子中,安卓程序猿一天的工作就是開發(fā)公司的項目,即androidCoder.dev()
,后來想要增強自己的功能,需要維護github上的開源項目,于是便使用了GithubFixer
來裝飾自己,即:new GithubFixer(androidCoder).dev()
,這樣在每次每天開發(fā)之前都會去先維護開源項目,再去開發(fā).
-
對于調(diào)用者,這完全是透明的,在所有基礎(chǔ)調(diào)用的位置,做以下替換就可以:
androidCoder.dev();//==> new GithubFixer(androidCoder).dev(); //當然也可以維護更多社區(qū)的項目... new OsChinaFixer(androidCoder).dev();
-
另外,
GithubFixer
不僅僅可以裝飾androidCoder
,IosCoder
-JavaCoder
等等都可以裝飾,例如:new GithubFixer(iosCoder).dev(); new GithubFixer(phpCoder).dev();
如果你使用繼承來為AndroidCoder(ios-php等等)增加fixBug功能,組件類別比較多的情況下,勢必會造成體系的臃腫,但是反觀裝飾者模式,由于是動態(tài)的為組價增強功能,則很好的避免了繼承體系臃腫的問題.
-
裝飾者模式可以鏈式調(diào)用,例如:
new PlayGame(new GithubFixer(iosCoder)).dev;//為組件增加維護開源項目,打游戲的功能
組件的原有功能沒有任何破壞,
Coder.dev()
保持內(nèi)部邏輯;裝飾者內(nèi)部會持有待裝飾者組件實例
Android源碼中裝飾者模式的使用
在源碼中裝飾者模式被使用的地方還是很多的,最典型的是Context體系,這里簡單分析一下:
- Context - 抽象組件
- ContextImpl - 具體組件:繼承自Context,實現(xiàn)了Context中的抽象方法;
- ContextWrapper - 裝飾者抽象:繼承Context,定義了一些增強方法,內(nèi)部持有Context引用
- ContextThemeWrapper - 具體裝飾者父類:實現(xiàn)了ContextWrapper中的抽象方法,提供一些通用實現(xiàn)
- Activity,Service,Application - 具體裝飾者實現(xiàn)類:實現(xiàn)全部的裝飾方法
關(guān)于作者
- 簡 書:uncochen
- github:ChenZhen
- 新浪微博:@Chen丶振
- Email:18620156376@163.com