设计模式-装饰者模式

装饰者模式 : 动态地将责任附加到对象上,或者说属性附加,如果要扩展,比继承的方式更加具有弹性

装饰者模式的优点与缺点
  1. 优点:装饰者模式与继承目的都是扩展对象的功能,但是装饰者模式可以提供比继承更多的灵活性。
  2. 缺点:由于装饰者模式更加灵活的特性,导致加入各种不同的小类,导致复杂度提升,不便于理解
UML图
装饰者模式
  • MilKyTea:装饰者与被装饰者的父类,可以是接口或者抽象类,可以用来定义行为和属性
  • ReadTea、SeasonTea:被装饰者,定义具体行为和属性
  • DecroateMilkyTea: 装饰者的抽象类,继承与MikyTea 用来装饰被装饰者。可以是抽象类与接口
  • Pudding、IceCream:装饰者的具体实现,用来装饰被装饰者的具体行为与属性
案例

平时工作之余,我们会叫上基友们一起点杯奶茶放松放松. 奶茶店有各种各样不同种类的奶茶让我们挑选, 但是我们不知道具体价格与品种,代码如下

定义奶茶基类 MilkyTea .java

public abstract class MilkyTea {
    /**
     * 奶茶名
     */
    public String name;


    public String getName() {
        return name;
    }

    /**
     * 奶茶价格
     *
     * @return
     */
    abstract public double cost();
}

知道奶茶之后,我们就要选择不同种类和价格的奶茶,比如我平时就喜欢点红茶拿铁

定义具体被装饰者 RedTea.java

public class RedTea extends MilkyTea {

    public RedTea() {
        name = "红茶拿铁";
    }


    @Override
    public double cost() {
        return 16;
    }
}

当我们选好奶茶与价格之后.我们会发现还有配料可以选择,比如布丁、燕麦、冰淇淋等,这个时候我们在没有了解装饰者模式之前可能立马会想到去父类加入几个字段就没问题了。虽然这样很快就能解决问题,但是如果是大型项目,突然来需求要改动,如果又回去改动之前的代码可能会引起别的地方错误,也说明我们程序的扩展型不强,并且还违背了 设计原则的 开闭原则, 这个时候我们就可以使用装饰者模式,给奶茶 动态添加布丁、燕麦等属性

开闭原则 一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。就相当于说,不修改原代码的情况下,扩展需求功能。

定义装饰者基类 DecorateMilkyTea .java

public abstract class DecorateMilkyTea extends MilkyTea {

    /**
     * 获取奶茶名
     *
     * @return
     */
    public abstract String getName();
}

定义装饰者 IceCream.java

  public class IceCream extends DecorateMilkyTea {
    //奶茶基类
    private MilkyTea milkyTeal;

    public IceCream(MilkyTea milkyTea) {
        //获取被装饰者
        this.milkyTeal = milkyTea;
    }


    @Override
    public String getName() {
        return milkyTeal.getName() + ",添加冰淇淋";
    }

    @Override
    public double cost() {
        return milkyTeal.cost() + 6.0;
    }
}

最后我们根据我们自己选择的奶茶+配料来计算结果

        //红茶
        MilkyTea milkyTea = new RedTea();
        System.out.println(milkyTea.getName() + " === " + milkyTea.cost());
        //红茶的基础上增加布丁配料(装饰者)
        milkyTea = new Pudding(milkyTea);
        System.out.println(milkyTea.getName() + " === " + milkyTea.cost());

        //四季拿铁
        MilkyTea seasonTea = new SeasonTea();
        //司机拿铁的基础上增加布丁与冰淇淋配料(装饰者)
        seasonTea = new IceCream(seasonTea);
        seasonTea = new Pudding(seasonTea);
        System.out.println(seasonTea.getName() + " === " + seasonTea.cost());

打印结果

红茶拿铁 总计花费 16.0
红茶拿铁,添加布丁 总计花费 20.2
四季拿铁,添加冰淇淋,添加布丁 总计花费 22.2
总结
  • 装饰者和被装饰者对象有相同的超类型,在需要原始对象(被装饰者)的场合,都可以用装饰过得对象代替原始对象。
  • 可以用一个或多个装饰者包装一个对象(被装饰者)
  • 装饰者模式 是多态的另一种体现
  • 装饰者模式 会导致出现很多小对象,过度使用会程序变的复杂
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 设计原则: 少用继承,多用组合 类应该对扩展开放,对修改关闭 目录 本文的结构如下: 什么是装饰者模式 为什么要用...
    w1992wishes阅读 1,116评论 0 7
  • 定义 装饰者模式:在不改变原类文件以及不使用继承的情况下,动态地将责任附加到对象上,从而实现动态拓展一个对象的功能...
    丶蓝天白云梦阅读 1,607评论 2 23
  • 前言 设计模式遍布我们编码的每一个角落,例如JAVA刚入门那会做的第一个窗口程序用的Swing中的ActionsL...
    柴码阅读 681评论 0 0
  • 概述 一般情况下,当我们想给一个类或对象添加功能的时候,有两种常用的方式: 继承:通过使用继承,我们可以使子类既能...
    骑着乌龟去看海阅读 507评论 0 1
  • 终有一天,我也希望能够背上行囊,远离家乡,到外面去闯一闯,不管外面的世界有多大的风浪,纵然会被拍打在沙滩上,至少我...
    孙家二爷阅读 181评论 0 0