裝飾者模式的理解

引入

在看數(shù)據(jù)庫連接池這一章內(nèi)容的時候,出現(xiàn)了面向接口編程和裝飾者模式的設(shè)計模式士修。利用裝飾者設(shè)計模式把數(shù)據(jù)庫連接池接口的實現(xiàn)類(被裝飾者)的close方法重寫(重寫其實也算是一種“添加”)了。

可能從上文很難看得出這是一個什么樣的問題,那么下文便用咖啡的例子幫助大家理解到底裝飾者模式解決了什么問題:

假設(shè)有四種咖啡:HouseBlend盔夜、DarkRoaat、Decaf堤魁、Espresso喂链。
同樣有四種可以搭配的選擇:Milk、Mocha妥泉、Soy椭微、Whip。

這四種咖啡有不同的價格盲链、同樣四種搭配也有不同的價格蝇率。當(dāng)我們把這個單子拿給顧客的時候、顧客可以任意點一種咖啡刽沾、可以任意搭配本慕。我們的目的是要統(tǒng)計每種搭配的價格、那我們要寫多少個類侧漓?最后的結(jié)果就是類爆炸锅尘!

當(dāng)我們要添加一個新的品種的時候、如果按照上面的方法布蔗、那我們就要新添加N多類來實現(xiàn)目的藤违。如何有效的解決這兩個問題?也許你有別的很多方法與思想纵揍、這里只是說明裝飾者模式的使用顿乒。
——來源于:Java設(shè)計模式之裝飾者模式

再舉一個例子,也是后面寫程序闡述的:
假設(shè)現(xiàn)在有一個進(jìn)服裝店的人
服裝店里有帽子泽谨、T恤璧榄、裙子

那么用程序來描述:
用Person類描述這個人
如果用繼承方法,
當(dāng)這個人戴上帽子的時候需要一個描述戴帽子的人的子類:HatPerson(繼承Person)
當(dāng)這個人穿上T恤的時候需要一個描述穿T恤的人的子類:TshirtPerson(繼承Person)
當(dāng)這個人穿上裙子的時候需要一個描述穿裙子的人的子類:SkirtPerson(繼承Person)
既戴帽子又穿T恤的時候需要一個描述的子類:HatTshirtPerson(繼承Person或同時繼承HatPerson與TshirtPerson)
......

可以看到隔盛,如果用這樣來描述問題犹菱,非常復(fù)雜拾稳。因為本身“繼承”描述的關(guān)系就是一類事物的細(xì)分吮炕,而不是類似這樣的對事物進(jìn)行某一部分的添油或加醋問題。而很明顯访得,利用“裝飾”這一設(shè)計概念龙亲,可以更靈活的描述這類問題陕凹。

什么是裝飾者模式?

為了更好描述鳄炉,需要對某個類(一個類可以看成描述的一個事物:例如一個人)的某個部分(類中的一個成員杜耙,例如一個人身上穿的衣服)進(jìn)行修改或重寫的這種問題的模式。

啥時候用拂盯?有啥樣的效果佑女?

由上可以總結(jié)出(附上代碼示例):

  • 當(dāng)需要對某個類進(jìn)行部分成員變量或方法的時候使用

A Sample
為了更加深刻地理解裝飾者模式,我們來看一個簡單的栗子谈竿。首先团驱,我們假設(shè)現(xiàn)在 有這樣一個需求:你有一家服裝店,賣各式各樣的衣服空凸,現(xiàn)在需要用一個系統(tǒng)來記錄客戶所要購買的衣服的總價嚎花,以便方便地結(jié)算。那么在這個例子里面呀洲,我們可以用裝飾者模式紊选,把客戶當(dāng)做被裝飾者,衣服是裝飾者道逗,這很直觀形象吧兵罢,接著我們來一步步實現(xiàn)需求。

Step 1憔辫、創(chuàng)建Component基類
因為總體對象是人趣些,所以我們可以把人抽象為基類,新建Person.java:

public abstract class Person {
  String description = "Unkonwn";

  public String getDescription()
  {
      return description;
  }

  public abstract double cost(); //子類應(yīng)該實現(xiàn)的方法
}

Step 2贰您、創(chuàng)建被裝飾者——ConcreteComponent
客戶分為很多種坏平,有兒童、青少年锦亦、成年人等舶替,因此我們可以創(chuàng)建不同的被裝飾者,這里我們創(chuàng)建青少年的被裝飾者杠园,新建Teenager.java:

public class Teenager extends Person {

  public Teenager() {
      description = "Shopping List:";
  }

  @Override
  public double cost() {
      //什么都沒買顾瞪,不用錢
      return 0;
  }
}

Step 3、創(chuàng)建Decorator
由于不同的部位有不同的衣物抛蚁,不能混為一談陈醒,比如說,衣服瞧甩、帽子钉跷、鞋子等,那么這里我們創(chuàng)建的Decorator為衣服和帽子肚逸,分別新建ClothingDecorator.java和HatDecorator.java:

public abstract class ClothingDecorator extends Person {

  public abstract String getDescription();
}

public abstract class HatDecorator extends Person {

  public abstract String getDescription();

}

Step 4爷辙、創(chuàng)建ConcreteDecorator
上面既然已經(jīng)創(chuàng)建了兩種Decorator彬坏,那么我們基于它們進(jìn)行拓展,創(chuàng)建出不同的裝飾者膝晾,對于Clothing栓始,我們新建Shirt.java,對于Hat血当,我們新建Casquette幻赚,其實可以根據(jù)不同類型的衣物創(chuàng)建更多不同的裝飾者,這里只是作為演示而創(chuàng)建了兩種臊旭。代碼如下所示:

public class Shirt extends ClothingDecorator {

  //用實例變量保存Person的引用
  Person person;

  public Shirt(Person person)
  {
      this.person = person;
  }

  @Override
  public String getDescription() {
      return person.getDescription() + "a shirt  ";
  }

  @Override
  public double cost() {
      return 100 + person.cost(); //實現(xiàn)了cost()方法坯屿,并調(diào)用了person的cost()方法,目的是獲得所有累加值
  }
 }
public class Casquette extends HatDecorator {

  Person person;

  public Casquette(Person person) {
      this.person = person;
  }
  @Override
  public String getDescription() {
      return person.getDescription() + "a casquette  "; //鴨舌帽
  }

  @Override
  public double cost() {
      return 75 + person.cost();
  }

}
  • 效果:能夠?qū)悾≒erson)的實例不斷的修改其成員
    public class Shopping {
    
      public static void main(String[] args) {
          Person person = new Teenager();
    
          person = new Shirt(person);//對一個person類實例加了T恤
          person = new Casquette(person);//對一個person類實例加了帽子
    
          System.out.println(person.getDescription() + " ¥ " +person.cost());
      }
    
    }
    

——代碼來源:學(xué)習(xí)巍扛、探究Java設(shè)計模式——裝飾者模式

可以怎么去細(xì)分裝飾者模式知識點呢领跛?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市撤奸,隨后出現(xiàn)的幾起案子吠昭,更是在濱河造成了極大的恐慌,老刑警劉巖胧瓜,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矢棚,死亡現(xiàn)場離奇詭異,居然都是意外死亡府喳,警方通過查閱死者的電腦和手機蒲肋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钝满,“玉大人兜粘,你說我怎么就攤上這事⊥溲粒” “怎么了孔轴?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碎捺。 經(jīng)常有香客問我路鹰,道長,這世上最難降的妖魔是什么收厨? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任晋柱,我火速辦了婚禮,結(jié)果婚禮上诵叁,老公的妹妹穿的比我還像新娘雁竞。我一直安慰自己,他們只是感情好黎休,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布浓领。 她就那樣靜靜地躺著,像睡著了一般势腮。 火紅的嫁衣襯著肌膚如雪联贩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天捎拯,我揣著相機與錄音泪幌,去河邊找鬼。 笑死署照,一個胖子當(dāng)著我的面吹牛祸泪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播建芙,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼没隘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了禁荸?” 一聲冷哼從身側(cè)響起右蒲,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赶熟,沒想到半個月后瑰妄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡映砖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年间坐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邑退。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡竹宋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出地技,到底是詐尸還是另有隱情逝撬,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布乓土,位于F島的核電站宪潮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏趣苏。R本人自食惡果不足惜狡相,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望食磕。 院中可真熱鬧尽棕,春花似錦、人聲如沸彬伦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至回官,卻和暖如春曹宴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背歉提。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工笛坦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人苔巨。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓版扩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侄泽。 傳聞我的和親對象是個殘疾皇子礁芦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容