裝飾模式又名包裝(Wrapper)模式柒啤。裝飾模式以對(duì)客戶端透明的方式擴(kuò)展對(duì)象的功能枫疆,是繼承關(guān)系的一個(gè)替代方案爵川。
裝飾器模式(Decorator Pattern)的核心作用就是動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)功能。適用于透明且動(dòng)態(tài)擴(kuò)展類功能時(shí)息楔。這點(diǎn)注意跟適配器模式的區(qū)別:
- 適配器模式主要是為了接口的轉(zhuǎn)換寝贡,而裝飾者模式關(guān)注的是通過(guò)組合來(lái)動(dòng)態(tài)的為被裝飾者注入新的功能或行為(即所謂的責(zé)任)。
- 適配器將一個(gè)對(duì)象包裝起來(lái)以改變其接口值依;裝飾者將一個(gè)對(duì)象包裝起來(lái)以增強(qiáng)新的行為和責(zé)任圃泡;而外觀將一群對(duì)象包裝起來(lái)以簡(jiǎn)化其接口
這里我們可能會(huì)有疑問(wèn):為什么不使用繼承的方式進(jìn)行功能的擴(kuò)展呢?首先裝飾器模式是基于已存在類的功能進(jìn)行擴(kuò)展愿险,如果使用繼承的方式進(jìn)行實(shí)現(xiàn)颇蜡,需求后期都可能進(jìn)行變動(dòng),這樣增加很多需求辆亏,會(huì)導(dǎo)致子類出現(xiàn)太多风秤,所以就增加功能來(lái)說(shuō),裝飾器模式相比生成子類更為靈活扮叨。所以為確保后期動(dòng)態(tài)增加現(xiàn)有類的職責(zé)缤弦,將具體功能職責(zé)劃分,同時(shí)繼承裝飾者模式彻磁。
裝飾者的UML圖
![UML](https://github.com/dengshiwei/work-summary/blob/master/work-blog/Java%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E8%A3%85%E9%A5%B0%E8%80%85%E6%A8%A1%E5%BC%8F/%E8%A3%85%E9%A5%B0%E8%80%85%E6%A8%A1%E5%BC%8F.png)
UML
裝飾模式的組成對(duì)象:
- 抽象組件化對(duì)象(Component):規(guī)范實(shí)例接口碍沐,約束具體行為
- 具體組件(ConcreteComponent):一個(gè)具體的接口實(shí)現(xiàn)類
- 裝飾角色(Decorator):持有一個(gè)Component對(duì)應(yīng)的引用,用來(lái)擴(kuò)展類的功能衷蜓;
- 具體的裝飾角色(ConcreteDecorator):根據(jù)需求進(jìn)行功能的擴(kuò)展累提;
實(shí)例代碼
講解裝飾模式使用最多的例子莫過(guò)于人穿衣服的例子,人穿衣戴帽就是裝飾的作用磁浇。
定義抽象類斋陪,人的角色
/**
* 定義一個(gè)人的抽象類
* @author Iflytek_dsw
*
*/
abstract class People {
private String name;
public People(String name){
this.name = name;
}
public abstract void dressed();
}
定義個(gè)具體的實(shí)例類實(shí)現(xiàn)接口,工人類
/**
* 抽象類的角色
* @author Iflytek_dsw
*
*/
class Worker extends People{
public Worker(String name) {
super(name);
}
@Override
public void dressed() {
System.out.println("穿工人裝");
}
}
定義裝飾者角色
class PeopleDecorator extends People{
private People people;
public PeopleDecorator(People people, String name) {
super(name);
this.people = people;
}
@Override
public void dressed() {
people.dressed();
}
}
定義裝飾的一個(gè)具體類
class HatDecorator extends PeopleDecorator{
public HatDecorator(People people, String name) {
super(people, name);
}
@Override
public void dressed() {
super.dressed();
wearHat();
}
private void wearHat(){
System.out.print("戴帽子");
}
}
定義客戶端
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
People people = new Worker("工人");
//給工人帶個(gè)帽子
HatDecorator hatDecorator = new HatDecorator(people, "工人");
hatDecorator.dressed();
}
}
從中可以看出來(lái),通過(guò)裝飾模式可以動(dòng)態(tài)給類增加新職責(zé)无虚。
優(yōu)點(diǎn)
- 裝飾模式與繼承關(guān)系的目的都是要擴(kuò)展對(duì)象的功能鞍匾,但是裝飾模式可以提供比繼承更多的靈活性。裝飾模式允許系統(tǒng)動(dòng)態(tài)決定“貼上”一個(gè)需要的“裝飾”骑科,或者除 掉一個(gè)不需要的“裝飾”橡淑。繼承關(guān)系則不同,繼承關(guān)系是靜態(tài)的咆爽,它在系統(tǒng)運(yùn)行前就決定了梁棠。
- 通過(guò)使用不同的具體裝飾類以及這些裝飾類的排列組合,設(shè)計(jì)師可以創(chuàng)造出很多不同行為的組合斗埂。
- 裝飾類和被裝飾類可以獨(dú)立發(fā)展符糊,不會(huì)相互耦合,裝飾模式是繼承的一個(gè)替代模式呛凶,裝飾模式可以動(dòng)態(tài)擴(kuò)展一個(gè)實(shí)現(xiàn)類的功能男娄。
缺點(diǎn)
- 多層裝飾比較復(fù)雜,類的數(shù)量略多