裝飾模式(包裝模式),也是結構型設計模式之一。它主要用于動態地對一個類或者對象添加新的功能,使得原有的類得到擴展,與代理模式不同的是該模式是直接對一個原有的對象進行擴展功能,而代理模式代理原對象的行為,而不是對原來的對象進行擴展。同時也不同于適配器模式,適配器模式是對一個接口或者類進行適配,使得在新的場合下也可以使用。而裝飾模式則是對對象進行擴展包裝,是繼承關系的代替方案。但比繼承的子類更加靈活,因為在關系上包裝的類與被包裝的類不是繼承關系。
定義:動態地對一個對象進行裝飾(包裝),以使得該對象具有更多的功能。
使用場景:
- 需要透明或者動態地擴展類的功能,即需要對類進行包裝。
與代理模式的區別:
- 可以將這種模式說成是代理模式的特殊情況,但裝飾模式是對類行為或者說功能進行擴展,增強類的功能。而代理模式強調通過一個代理對象對原對象的行為施加控制,而不對類本身擴展功能。這兩種模式很相似,因此要細心加以區分。
裝飾模式的例子在生活中也隨處可見,生活中的萬物可以都需要進行包裝,如水果,店鋪,教室等等,甚至我們人也要進行包裝,如穿衣服,帶帽子等等以便我們自己的形象更加好。所以,下面以生活中的一個小例子來用代碼實現裝飾模式,以便我們對裝飾模式有一個清晰的認識。
假設我們開了一個淘寶店鋪,那么我們在賣商品前要對我們的淘寶店進行裝飾。什么logo,公告,背景音樂等等。
代碼實現:
店鋪(接口)
~~~
/**
* 店鋪(接口),淘寶給商家開放的一個接口
* @author lt
*
*/
public interface ShopI {
/**
* 展示
*/
public void show();
}
~~~
淘寶店(被裝飾的對象)
~~~
public class TaobaoShop implements ShopI{
private String name;
public TaobaoShop(String name){
this.name = name;
}
/**
* 展示
*/
@Override
public void show() {
System.out.println("名字:"+name);
}
}
~~~
裝飾后的淘寶店(裝飾對象)
~~~
public class DecoratedShop implements ShopI{
private ShopI shop; // 持有一個要裝飾對象的引用,通過該引用對對象進行裝飾
public DecoratedShop(ShopI shop){
this.shop = shop;
}
/**
* logo,我們擴展的功能
*/
private void logo(){
System.out.println("logo:特賣Logo");
}
/**
* 背景音樂,我們擴展的功能
*/
private void bgMusic(){
System.out.println("背景音樂:你是我的小啊小蘋果,怎么愛你都不嫌多...");
}
/**
* 公告,我們擴展的功能
*/
private void notice(){
System.out.println("公告:這是一家專門做特賣的店鋪,原裝正品,童叟無欺!");
}
@Override
public void show() {
shop.show();
logo(); // 上傳logo
notice(); // 發布公告
bgMusic(); // 添加背景音樂
}
}
~~~
說明:這里裝飾對象和被裝飾對象實現相同的接口是為了使得裝飾對象對原對象功能裝飾包裝得對客戶端更加能透明,也可以不用實現相同的接口,如果裝飾對象通過繼承被裝飾對象以擴展它的功能的話,那就是繼承關系了。
測試:
~~~
public class Test {
public static void main(String[] args) {
// 申請一個淘寶店,叫微真會
TaobaoShop newShop = new TaobaoShop("微真會");
System.out.println("剛申請的店鋪:");
newShop.show();
// 對這個店鋪進行裝飾
DecoratedShop decoratedShop = new DecoratedShop(newShop);
System.out.println("裝飾后的店鋪:");
decoratedShop.show();
}
}
~~~
Run AS:

如果我們在對原對象(newShop)進行*show()*方法調用,那么還是會顯示只有一個名字,因為我們進僅僅是對原對象進行了一層包裝,而并沒有改變原對象的功能,原對象脫離了裝飾它的對象那么就只有原來的功能了,就像我們人一樣,卸掉身上的裝飾品后還是我們自己,但就是更不那么好看了。
總結:
裝飾模式特別容易理解,因為這樣的例子在我們生活中隨處可見,完全可以通過字面進行理解,即裝飾。但我們要注意細心區分裝飾模式和代理模式的區別,因為這兩種模式特別像,區別在于代理原對象的行為還是要擴展原對象的行為以裝飾包裝原對象。