簡單詳解:
1、概念
動態地給一個對象添加一些額外的職責。就增加功能來說, 裝飾模式相比生成子類更爲靈活。該模式以對客戶端透明的方式擴展對象的功能。
2、使用場景
- 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。和繼承類似添加相應的職責。
- 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因爲類定義被隱藏,或類定義不能用於生成子類。
3、UML結構圖分析
- 抽象構件(Component)角色:給出一個抽象接口,已規範準備接收附加責任的對象。
- 具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類
- 裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。
- 具體裝飾(ConcreteDecorator)角色:負責給構件對象“貼上”附加的責任。
4、實際代碼分析
/**
* 裝飾類Component,所有類的父類
*/
public interface Component {
void sampleOperation();
}
/**
* 實現抽象部件,具體裝飾過程還是交給子類實現
*/
public class Decorator implements Component {
private Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public void sampleOperation() {
component.sampleOperation();
}
}
/**
* 需要裝扮的類
*/
public class ConcreteComponent implements Component{
@Override
public void sampleOperation() {
}
}
/**
* 具體實現
*/
public class ConcreateDecoratorA extends Decorator{
public ConcreateDecoratorA(Component component) {
super(component);
}
@Override
public void sampleOperation() {
super.sampleOperation();
addPingShengm();
}
/**
* 新增業務方法
*/
private void addPingShengm() {
System.out.println("添加繪彩1");
}
}
/**
* 具體實現
*/
public class ConcreateDecoratorB extends Decorator{
public ConcreateDecoratorB(Component component) {
super(component);
}
@Override
public void sampleOperation() {
super.sampleOperation();
addPingShengm();
}
/**
* 新增業務方法
*/
private void addPingShengm() {
System.out.println("添加繪彩2");
}
}
舉一個實際例子:
工廠需要產生多種水杯,有瓶身繪彩,有不鏽鋼蓋被子,也有不鏽鋼蓋和瓶身繪彩的杯子。(等各種需求)
假如說採用繼承子類的方式。如下code:
/**
* 創建水杯的接口包含四個方法,底座,蓋子,瓶身,一個實現功能product
*/
public interface IShuiBei {
void dizuo();
void gaizi();
void pingsheng();
void product();
}
/**
* 水晶杯實現類
*/
public class ShuiJInBei implements IShuiBei,Component {
@Override
public void dizuo() {
System.out.println("水晶底座");
}
@Override
public void gaizi() {
System.out.println("水晶蓋子");
}
@Override
public void pingsheng() {
System.out.println("水晶瓶身");
}
@Override
public void product() {
dizuo();
gaizi();
pingsheng();
}
}
/**
* 添加繪彩的水晶杯
*/
public class HuiCaiShuiJinBei extends ShuiJInBei{
@Override
public void pingsheng() {
super.pingsheng();
System.out.println("添加繪彩");
}
}
/**
* 不鏽鋼杯子蓋的水晶杯
*/
public class HuiJinGangGaiBei extends ShuiJInBei{
@Override
public void gaizi() {
System.out.println("不鏽鋼杯蓋");
}
}
/**
* 不鏽鋼杯子蓋的水晶杯帶彩繪
*/
public class HuiCaiShuiJinGangGaiBei extends ShuiJInBei{
@Override
public void gaizi() {
System.out.println("不鏽鋼杯蓋");
}
@Override
public void pingsheng() {
super.pingsheng();
System.out.println("添加繪彩");
}
}
//運行
HuiCaiShuiJinBei huiCaiShuiJinBei = new HuiCaiShuiJinBei();
HuiCaiShuiJinGangGaiBei huiCaiShuiJinGangGaiBei = new HuiCaiShuiJinGangGaiBei();
ShuiJInBei shuiJInBei = new ShuiJInBei();
huiCaiShuiJinBei.product();
huiCaiShuiJinGangGaiBei.product();
shuiJInBei.product();
一共創建三個子類,一個父類,當然如果需求更多的話,子類會不斷的增加。
裝飾類實現如上功能code:
/**
* 實現抽象部件
*/
public class ShuijinbeiDecorator implements IShuiBei{
IShuiBei iShuiBei;
public ShuijinbeiDecorator(IShuiBei iShuiBei){
this.iShuiBei = iShuiBei;
}
@Override
public void dizuo() {
iShuiBei.dizuo();
}
@Override
public void gaizi() {
iShuiBei.gaizi();
}
@Override
public void pingsheng() {
iShuiBei.pingsheng();
}
@Override
public void product() {
dizuo();
gaizi();
pingsheng();
}
}
/**
* 鋼蓋實現類
*/
public class GangGaiDecorator extends ShuijinbeiDecorator{
public GangGaiDecorator(IShuiBei iShuiBei) {
super(iShuiBei);
}
@Override
public void gaizi() {
System.out.println("不鏽鋼杯蓋");
}
}
/**
* 彩繪實現類
*/
public class CaihuiDecorator extends ShuijinbeiDecorator{
public CaihuiDecorator(IShuiBei iShuiBei) {
super(iShuiBei);
}
@Override
public void pingsheng() {
super.pingsheng();
System.out.println("添加繪彩");
}
}
//運行
IShuiBei iShuiBei = new ShuiJInBei();
iShuiBei.product();
iShuiBei = new CaihuiDecorator(iShuiBei);
iShuiBei.product();
iShuiBei = new GangGaiDecorator(iShuiBei);
iShuiBei.product();
iShuiBei = new ShuiJInBei();
iShuiBei = new GangGaiDecorator(iShuiBei);
iShuiBei.product();
看到如上代碼你大概會恍然大悟,裝飾模式如果在你的子類特別多,用裝飾模式很好,但是比較容易出錯哦。
裝飾模式的優點
- 裝飾模式與繼承關係的目的都是要拓展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。
- 裝飾模式允許系統動態決定“貼上”一個需要的“裝飾”,或者“除掉”一個不需要的“裝飾”。繼承關係則不同,繼承關係是靜態的,它在系統運行前就決定了。
- 可以對一個對象進行多次裝飾,通過使用不同的具體裝飾類以及這些裝飾類的排列組合。
裝飾模式的缺點
由於使用裝飾模式,可以比使用繼承關係需要較少數目的類。使用較少的類,當然使設計比較易於進行。但是,在另外一方面,使用裝飾模式會產生比使用繼承關係所產生的更多的對象。而更多的對象會使得查找錯誤更爲困難,特別是這些對象在看上去極爲相似的時候。
裝飾模式在Android中的實際應用
context類簇