java设计模式初探之装饰者_JAVA设计模式初探之装饰者模式
裝飾者模式
1、意圖:?動(dòng)態(tài)地給一個(gè)對象添加一些額外的職責(zé)。就增加功能來說, Decorator模式相比生成子類更為靈活。該模式以對客 戶端透明的方式擴(kuò)展對象的功能。
2、適用環(huán)境
(1)在不影響其他對象的情況下,以動(dòng)態(tài)、透明的方式給單個(gè)對象添加職責(zé)。
(2)處理那些可以撤消的職責(zé)。
(3)當(dāng)不能采用生成子類的方法進(jìn)行擴(kuò)充時(shí)。一種情況是,可能有大量獨(dú)立的擴(kuò)展,為支持每一種組合將產(chǎn)生大量的 子類,使得子類數(shù)目呈爆炸性增長。另一種情況可能是因?yàn)轭惗x被隱藏,或類定義不能用于生成子類。
3、參與者
1.Component(被裝飾對象的基類)
定義一個(gè)對象接口,可以給這些對象動(dòng)態(tài)地添加職責(zé)。
2.ConcreteComponent(具體被裝飾對象)
定義一個(gè)對象,可以給這個(gè)對象添加一些職責(zé)。
3.Decorator(裝飾者抽象類)
維持一個(gè)指向Component實(shí)例的引用,并定義一個(gè)與Component接口一致的接口。
4.ConcreteDecorator(具體裝飾者)
具體的裝飾對象,給內(nèi)部持有的具體被裝飾對象,增加具體的職責(zé)。
4、類圖
5、涉及角色
(1)抽象組件:定義一個(gè)抽象接口,來規(guī)范準(zhǔn)備附加功能的類
(2)具體組件:將要被附加功能的類,實(shí)現(xiàn)抽象構(gòu)件角色接口
(3)抽象裝飾者:持有對具體構(gòu)件角色的引用并定義與抽象構(gòu)件角色一致的接口
(4)具體裝飾:實(shí)現(xiàn)抽象裝飾者角色,負(fù)責(zé)對具體構(gòu)件添加額外功能。
1 /定義被裝飾者2 public interfaceHuman {3 public voidwearClothes();4
5 public voidwalkToWhere();6 }7
8 //定義裝飾者
9 public abstract classDecorator implements Human {10 privateHuman human;11
12 publicDecorator(Human human) {13 this.human =human;14 }15
16 public voidwearClothes() {17 human.wearClothes();18 }19
20 public voidwalkToWhere() {21 human.walkToWhere();22 }23 }24
25 //下面定義三種裝飾,這是第一個(gè),第二個(gè)第三個(gè)功能依次細(xì)化,即裝飾者的功能越來越多
26 public classDecorator_zero extends Decorator {27
28 publicDecorator_zero(Human human) {29 super(human);30 }31
32 public voidgoHome() {33 System.out.println("進(jìn)房子。。");34 }35
36 public voidfindMap() {37 System.out.println("書房找找Map。。");38 }39
40 @Override41 public voidwearClothes() {42 //TODO Auto-generated method stub
43 super.wearClothes();44 goHome();45 }46
47 @Override48 public voidwalkToWhere() {49 //TODO Auto-generated method stub
50 super.walkToWhere();51 findMap();52 }53 }54
55 public classDecorator_first extends Decorator {56
57 publicDecorator_first(Human human) {58 super(human);59 }60
61 public voidgoClothespress() {62 System.out.println("去衣柜找找看。。");63 }64
65 public voidfindPlaceOnMap() {66 System.out.println("在Map上找找。。");67 }68
69 @Override70 public voidwearClothes() {71 //TODO Auto-generated method stub
72 super.wearClothes();73 goClothespress();74 }75
76 @Override77 public voidwalkToWhere() {78 //TODO Auto-generated method stub
79 super.walkToWhere();80 findPlaceOnMap();81 }82 }83
84 public classDecorator_two extends Decorator {85
86 publicDecorator_two(Human human) {87 super(human);88 }89
90 public voidfindClothes() {91 System.out.println("找到一件D&G。。");92 }93
94 public voidfindTheTarget() {95 System.out.println("在Map上找到神秘花園和城堡。。");96 }97
98 @Override99 public voidwearClothes() {100 //TODO Auto-generated method stub
101 super.wearClothes();102 findClothes();103 }104
105 @Override106 public voidwalkToWhere() {107 //TODO Auto-generated method stub
108 super.walkToWhere();109 findTheTarget();110 }111 }112
113 //定義被裝飾者,被裝飾者初始狀態(tài)有些自己的裝飾
114 public classPerson implements Human {115
116 @Override117 public voidwearClothes() {118 //TODO Auto-generated method stub
119 System.out.println("穿什么呢。。");120 }121
122 @Override123 public voidwalkToWhere() {124 //TODO Auto-generated method stub
125 System.out.println("去哪里呢。。");126 }127 }128 //測試類,看一下你就會(huì)發(fā)現(xiàn),跟java的I/O操作有多么相似
129 public classTest {130 public static voidmain(String[] args) {131 Human person = newPerson();132 Decorator decorator = new Decorator_two(newDecorator_first(133 newDecorator_zero(person)));134 decorator.wearClothes();135 decorator.walkToWhere();136 }137 }
運(yùn)行結(jié)果:
其實(shí)就是進(jìn)房子找衣服,然后找地圖這樣一個(gè)過程,通過裝飾者的三層裝飾,把細(xì)節(jié)變得豐富。
關(guān)鍵點(diǎn):
1、Decorator抽象類中,持有Human接口,方法全部委托給該接口調(diào)用,目的是交給該接口的實(shí)現(xiàn)類即子類進(jìn)行調(diào)用。
2、Decorator抽象類的子類(具體裝飾者),里面都有一個(gè)構(gòu)造方法調(diào)用super(human),這一句就體現(xiàn)了抽象類依賴于子類實(shí)現(xiàn)即抽象依賴于實(shí)現(xiàn)的原則。因?yàn)闃?gòu)造里面參數(shù)都是Human接口,只要是該Human的實(shí)現(xiàn)類都可以傳遞進(jìn)去,即表現(xiàn)出Decorator dt = new Decorator_second(new Decorator_first(new Decorator_zero(human)));這種結(jié)構(gòu)的樣子。所以當(dāng)調(diào)用dt.wearClothes();dt.walkToWhere()的時(shí)候,又因?yàn)槊總€(gè)具體裝飾者類中,都先調(diào)用super.wearClothes和super.walkToWhere()方法,而該super已經(jīng)由構(gòu)造傳遞并指向了具體的某一個(gè)裝飾者類(這個(gè)可以根據(jù)需要調(diào)換順序),那么調(diào)用的即為裝飾類的方法,然后才調(diào)用自身的裝飾方法,即表現(xiàn)出一種裝飾、鏈?zhǔn)降念愃朴谶^濾的行為。
3、具體被裝飾者類,可以定義初始的狀態(tài)或者初始的自己的裝飾,后面的裝飾行為都在此基礎(chǔ)上一步一步進(jìn)行點(diǎn)綴、裝飾。
4、裝飾者模式的設(shè)計(jì)原則為:對擴(kuò)展開放、對修改關(guān)閉,這句話體現(xiàn)在我如果想擴(kuò)展被裝飾者類的行為,無須修改裝飾者抽象類,只需繼承裝飾者抽象類,實(shí)現(xiàn)額外的一些裝飾或者叫行為即可對被裝飾者進(jìn)行包裝。所以:擴(kuò)展體現(xiàn)在繼承、修改體現(xiàn)在子類中,而不是具體的抽象類,這充分體現(xiàn)了依賴倒置原則,這是自己理解的裝飾者模式。
說的不清楚,有些只可意會(huì)不可言傳的感覺,多看幾遍代碼,然后自己敲出來運(yùn)行一下,基本上就領(lǐng)悟了。
下面這個(gè)例子也有助于理解 裝飾的流程和作用
現(xiàn)在需要一個(gè)漢堡,主體是雞腿堡,可以選擇添加生菜、醬、辣椒等等許多其他的配料,這種情況下就可以使用裝飾者模式。
漢堡基類(被裝飾者,相當(dāng)于上面的Human)
package decorator;
public abstract class Humburger {
protected String name ;
public String getName(){
return name;
}
public abstract double getPrice();
}
雞腿堡類(被裝飾者的初始狀態(tài),有些自己的簡單裝飾,相當(dāng)于上面的Person)
package decorator;
public class ChickenBurger extends Humburger {
public ChickenBurger(){
name = "雞腿堡";
}
@Override
public double getPrice() {
return 10;
}
}
配料的基類(裝飾者,用來對漢堡進(jìn)行多層裝飾,每層裝飾增加一些配料,相當(dāng)于上面Decorator)
package decorator;
public abstract class Condiment extends Humburger {
public abstract String getName();
}
生菜(裝飾者的第一層,相當(dāng)于上面的decorator_zero)
package decorator;
public class Lettuce extends Condiment {
Humburger humburger;
public Lettuce(Humburger humburger){
this.humburger = humburger;
}
@Override
public String getName() {
return humburger.getName()+" 加生菜";
}
@Override
public double getPrice() {
return humburger.getPrice()+1.5;
}
}
辣椒(裝飾者的第二層,相當(dāng)于上面的decorator_first)
package decorator;
public class Chilli extends Condiment {
Humburger humburger;
public Chilli(Humburger humburger){
this.humburger = humburger;
}
@Override
public String getName() {
return humburger.getName()+" 加辣椒";
}
@Override
public double getPrice() {
return humburger.getPrice(); //辣椒是免費(fèi)的哦
}
}
測試類
package decorator;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
Humburger humburger = new ChickenBurger();
System.out.println(humburger.getName()+" 價(jià)錢:"+humburger.getPrice());
Lettuce lettuce = new Lettuce(humburger);
System.out.println(lettuce.getName()+" 價(jià)錢:"+lettuce.getPrice());
Chilli chilli = new Chilli(humburger);
System.out.println(chilli.getName()+" 價(jià)錢:"+chilli.getPrice());
Chilli chilli2 = new Chilli(lettuce);
System.out.println(chilli2.getName()+" 價(jià)錢:"+chilli2.getPrice());
}
}
輸出
雞腿堡 價(jià)錢:10.0
雞腿堡 加生菜 價(jià)錢:11.5
雞腿堡 加辣椒 價(jià)錢:10.0
雞腿堡 加生菜 加辣椒 價(jià)錢:11.5
作者:jason0539
總結(jié)
以上是生活随笔為你收集整理的java设计模式初探之装饰者_JAVA设计模式初探之装饰者模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python迭代器举例_如何最简单、通俗
- 下一篇: asp.net ajax控件工具集 Au