
簡(jiǎn)述
裝飾者模式(Decorator Pattern)也稱為包裝模式(Wrapper Pattern),以透明動(dòng)態(tài)的方式來(lái)動(dòng)態(tài)擴(kuò)展對(duì)象的功能,也是繼承關(guān)系的一種代替方案。

- Component:抽象組件(可以是抽象類或者接口),被裝飾的原始對(duì)象
- ConcreteComponent:具體實(shí)現(xiàn)類,被裝飾的具體對(duì)象
- Decorator:抽象裝飾者,職責(zé)就是為了裝飾我們的組件對(duì)象,內(nèi)部一定要有一個(gè)指向組件對(duì)象的引用
- ConcreteDecoratorA:裝飾者具體實(shí)現(xiàn)類,只對(duì)抽象裝飾者做出具體實(shí)現(xiàn)
- ConcreteDecoratorB:同上
舉個(gè)栗子
人定義為抽象類,有一個(gè)抽象方法eat()
public abstract class Person {
public abstract void eat();
}
接著創(chuàng)建一個(gè)NormalPerson類繼承Person,對(duì)eat()方法有了具體實(shí)現(xiàn);NormalPerson類就是我們需要裝飾的對(duì)象。
public class NormalPerson extends Person {
@Override
public void eat() {
System.out.println("吃飯");
}
}
這里定義一個(gè)PersonFood類來(lái)表示裝飾者的抽象類,保持了一個(gè)對(duì)Person的引用,可以方便調(diào)用具體被裝飾的對(duì)象方法,這樣就可以方便的對(duì)其進(jìn)行擴(kuò)展功能,并且不改變?cè)惖膶哟谓Y(jié)構(gòu)。
public class PersonFood extends Person {
private Person person;
public PersonFood(Person person){
this.person = person;
}
@Override
public void eat() {
person.eat();
}
}
接著就是具體的裝飾類了,這兩個(gè)類沒(méi)有本質(zhì)上的區(qū)別,都是為了擴(kuò)展NormalPerson類,不修改原有類的方法和結(jié)構(gòu)
public class ExpensiveFood extends PersonFood {
public ExpensiveFood(Person person) {
super(person);
}
@Override
public void eat() {
super.eat();
eatSteak();
drinkRedWine();
}
public void eatSteak(){
System.out.println("吃牛排");
}
public void drinkRedWine(){
System.out.println("喝拉菲");
}
}
public class CheapFood extends PersonFood {
public CheapFood(Person person) {
super(person);
}
@Override
public void eat() {
super.eat();
eatNoodles();
}
public void eatNoodles(){
System.out.println("吃面條");
}
}
客戶端代碼
public class Client {
public static void main(String[] args){
Person person = new NormalPerson();
PersonFood cheapFood = new CheapFood(person);
cheapFood.eat();
PersonFood expensiveFood = new ExpensiveFood(person);
expensiveFood.eat();
}
}
android中的裝飾者模式
在android中,Context就是典型的裝飾者模式,Context是抽象類,真實(shí)的功能實(shí)現(xiàn)實(shí)在ComtextImpl中完成,ComtextImpl就是Context的實(shí)現(xiàn)類;然后看源碼會(huì)發(fā)現(xiàn)Activity是繼承于ContextThemeWrapper而不是直接繼承于Context。其中ContextThemeWrapper 繼承于ContextWrapper,而ContextWrapper繼承于Context。這里就可以看出來(lái)一點(diǎn)裝飾者模式了,其中裝飾者所調(diào)用的方法就是startActivity方法,在ContextWrapper中會(huì)發(fā)現(xiàn)startActivity方法調(diào)用了ComtextImpl中對(duì)應(yīng)的方法,實(shí)質(zhì)上ContextWrapper中所有方法都僅僅是調(diào)用了ComtextImpl中的方法,這就和裝飾者模式基本就對(duì)應(yīng)上了。
優(yōu)點(diǎn)
- 裝飾者模式與繼承關(guān)系的目的都是要擴(kuò)展對(duì)象的功能,但是裝飾者模式可以提供比繼承更多的靈活性。
- 通過(guò)使用不同的具體裝飾類以及這些裝飾類的排列組合,設(shè)計(jì)師可以創(chuàng)造出很多不同行為的組合。
缺點(diǎn)
- 這種比繼承更加靈活機(jī)動(dòng)的特性,也同時(shí)意味著更加多的復(fù)雜性。
- 裝飾模式會(huì)導(dǎo)致設(shè)計(jì)中出現(xiàn)許多小類,如果過(guò)度使用,會(huì)使程序變得很復(fù)雜。
- 裝飾模式是針對(duì)抽象組件(Component)類型編程。但是,如果你要針對(duì)具體組件編程時(shí),就應(yīng)該重新思考你的應(yīng)用架構(gòu),以及裝飾者是否合適。當(dāng)然也可以改變
Component接口,增加新的公開的行為,實(shí)現(xiàn)“半透明”的裝飾者模式。在實(shí)際項(xiàng)目中要做出最佳選擇。
與代理模式的區(qū)別
其實(shí)裝飾者模式和代理模式很像,但是兩者的目的不盡相同。裝飾者模式是以對(duì)客戶端透明的方式擴(kuò)展對(duì)象的功能,是繼承關(guān)系的一個(gè)替代方案;而代理模式則是一個(gè)給對(duì)象提供一個(gè)代理對(duì)象,并由代理對(duì)象來(lái)控制對(duì)原有對(duì)象的引用。
裝飾者模式為本裝飾的對(duì)象進(jìn)行功能擴(kuò)展;代理模式對(duì)代理對(duì)象進(jìn)行控制,但不做功能擴(kuò)展