裝飾者模式(Decorator Pattern):裝飾者模式是在沒必要改變原類文件和使用繼承的狀況下,動態地擴展一個對象的功能。它是經過建立一個裝飾對象,來包裹真實的對象,即被裝飾對象。測試
稍微百度一下,看到都是亂七八糟的文章。。這裏,我用舉例子的方法來給介紹裝飾者模式。this
從實際出發,把生活中的例子活用到代碼中能更好地理解。好比說,工人有不少種,水管工、木匠之類的,不一樣的職業也有分不一樣的公司的,A公司、B公司等等。下面我弄了一個圖來講明工人、具體工種、不一樣工種在不一樣公司之間的關係:spa
同時,也拋出了一個疑問,這些層次關係要怎麼表示,該用繼承嗎?固然能夠用繼承,可是有一個問題,假如還有不少別的工種呢?還有不少別的公司呢?若是每間公司都有全部的工種,那麼,一共須要的類太多了吧,這樣會形成所謂的「類爆炸」。所以,咱們用裝飾者模式來解決這個問題。code
1.新建一個公共接口Worker對象
1 //新建一個Worker接口 2 interface Worker{ 3 public void doSomeWork(); 4 }
2.添加各類職業,實現Worker接口blog
//新建一個Plunmber類,實現Worker接口 class Plumber implements Worker{ public void doSomeWork(){ System.out.println("修水管"); } } //新建一個Carpenter類,實現Worker接口 class Carpenter implements Worker{ public void doSomeWork(){ System.out.println("修門窗"); } }
3.添加公司,實現Worker接口,該部分體現裝飾者模式的核心。繼承
1 //新建一個AWorker類,實現Worker接口 2 class AWorker implements Worker{ 3 private Worker worker; 4 public AWorker(Worker worker){ 5 this.worker = worker; 6 } 7 public void doSomeWork(){ 8 System.out.println("你好"); //A公司對員工的要求 9 worker.doSomeWork(); 10 } 11 } 12 13 //新建一個BWorker類,實現Worker接口 14 class BWorker implements Worker{ 15 private Worker worker; 16 public BWorker(Worker worker){ 17 this.worker = worker; 18 } 19 public void doSomeWork(){ 20 System.out.println("進門前穿鞋套"); //B公司對員工的要求 21 worker.doSomeWork(); 22 } 23 }
4.寫一個Demo來測試裝飾者模式接口
1 public class Decorator 2 { 3 public static void main(String[] args) 4 { 5 //實例化一個Plumber對象,隸屬於A公司 6 Plumber plumber = new Plumber(); 7 AWorker aWorker = new AWorker(plumber); 8 aWorker.doSomeWork(); 9 10 //實例化一個Carpenter對象,隸屬於B公司 11 Carpenter carpenter = new Carpenter(); 12 BWorker bWorker = new BWorker(carpenter); 13 bWorker.doSomeWork(); 14 } 15 }
運行結果以下:class
分析:結合本文一開始的介紹,AWorker和BWorker其實就是裝飾者,而Plumber和Carpenter是被裝飾者,即真實須要的對象,而由於Worker接口是Plumber和Carpenter的父類,根據多態性原理,傳值成功,在裝飾者對象的doSomeWork()方法中,worker.doSomeWork()方法會根據裝飾者對象在實例化過程當中的具體參數而調用對應的被裝飾者的doSomeWork()方法。裝飾者模式的特徵就是:被裝飾者類(裝飾者類 裝飾者對象)。原理
總結:裝飾者模式的好處就是省略了衆多繁瑣的類之間的繼承,用這種方法比用繼承要更加靈活。當有新的類加入時,不須要讓下層的其餘類來繼承這個新的類,只須要讓這個新的類實現頂層的接口就能夠了。固然這是它的優勢之一,這個模式也有不足之處,當已存在的類須要改變時,也只能老老實實地找出那個類而後修改了。