装饰者模式的理解

引入

在看数据库连接池这一章内容的时候,出现了面向接口编程和装饰者模式的设计模式。利用装饰者设计模式把数据库连接池接口的实现类(被装饰者)的close方法重写(重写其实也算是一种“添加”)了。

可能从上文很难看得出这是一个什么样的问题,那么下文便用咖啡的例子帮助大家理解到底装饰者模式解决了什么问题:

假设有四种咖啡:HouseBlend、DarkRoaat、Decaf、Espresso。
同样有四种可以搭配的选择:Milk、Mocha、Soy、Whip。

这四种咖啡有不同的价格、同样四种搭配也有不同的价格。当我们把这个单子拿给顾客的时候、顾客可以任意点一种咖啡、可以任意搭配。我们的目的是要统计每种搭配的价格、那我们要写多少个类?最后的结果就是类爆炸!

当我们要添加一个新的品种的时候、如果按照上面的方法、那我们就要新添加N多类来实现目的。如何有效的解决这两个问题?也许你有别的很多方法与思想、这里只是说明装饰者模式的使用。
——来源于:Java设计模式之装饰者模式

再举一个例子,也是后面写程序阐述的:
假设现在有一个进服装店的人
服装店里有帽子、T恤、裙子

那么用程序来描述:
用Person类描述这个人
如果用继承方法,
当这个人戴上帽子的时候需要一个描述戴帽子的人的子类:HatPerson(继承Person)
当这个人穿上T恤的时候需要一个描述穿T恤的人的子类:TshirtPerson(继承Person)
当这个人穿上裙子的时候需要一个描述穿裙子的人的子类:SkirtPerson(继承Person)
既戴帽子又穿T恤的时候需要一个描述的子类:HatTshirtPerson(继承Person或同时继承HatPerson与TshirtPerson)
......

可以看到,如果用这样来描述问题,非常复杂。因为本身“继承”描述的关系就是一类事物的细分,而不是类似这样的对事物进行某一部分的添油或加醋问题。而很明显,利用“装饰”这一设计概念,可以更灵活的描述这类问题。

什么是装饰者模式?

为了更好描述,需要对某个类(一个类可以看成描述的一个事物:例如一个人)的某个部分(类中的一个成员,例如一个人身上穿的衣服)进行修改或重写的这种问题的模式。

啥时候用?有啥样的效果?

由上可以总结出(附上代码示例):

  • 当需要对某个类进行部分成员变量或方法的时候使用

A Sample
为了更加深刻地理解装饰者模式,我们来看一个简单的栗子。首先,我们假设现在 有这样一个需求:你有一家服装店,卖各式各样的衣服,现在需要用一个系统来记录客户所要购买的衣服的总价,以便方便地结算。那么在这个例子里面,我们可以用装饰者模式,把客户当做被装饰者,衣服是装饰者,这很直观形象吧,接着我们来一步步实现需求。

Step 1、创建Component基类
因为总体对象是人,所以我们可以把人抽象为基类,新建Person.java:

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

  public String getDescription()
  {
      return description;
  }

  public abstract double cost(); //子类应该实现的方法
}

Step 2、创建被装饰者——ConcreteComponent
客户分为很多种,有儿童、青少年、成年人等,因此我们可以创建不同的被装饰者,这里我们创建青少年的被装饰者,新建Teenager.java:

public class Teenager extends Person {

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

  @Override
  public double cost() {
      //什么都没买,不用钱
      return 0;
  }
}

Step 3、创建Decorator
由于不同的部位有不同的衣物,不能混为一谈,比如说,衣服、帽子、鞋子等,那么这里我们创建的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、创建ConcreteDecorator
上面既然已经创建了两种Decorator,那么我们基于它们进行拓展,创建出不同的装饰者,对于Clothing,我们新建Shirt.java,对于Hat,我们新建Casquette,其实可以根据不同类型的衣物创建更多不同的装饰者,这里只是作为演示而创建了两种。代码如下所示:

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(); //实现了cost()方法,并调用了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();
  }

}
  • 效果:能够对基类(Person)的实例不断的修改其成员
    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());
      }
    
    }
    

——代码来源:学习、探究Java设计模式——装饰者模式

可以怎么去细分装饰者模式知识点呢?

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容