设计模式之装饰者模式(Decorator Pattern)

What:

装饰者模式又名包装(Wrapper)模式。装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

Why:

优点:
1.装饰者模式比继承灵活性,在不改变原有对象的情况下给对象扩展功能,符合开闭原则。

继承关系是静态的,在编译的时候就已经决定了行为,不便于控制增加行为的方式和时机。

2.装饰者模式可以动态使用不同的装饰类排列组合,创造出多样的行为组合。

缺点:

1.装饰模式会导致设计出大量的ConcreteDecorator类,增加系统的复杂性。
2.对于多次装饰的对象,一旦出现错误,排错繁琐;

Where:

1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2.需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
3.当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

How:

在学习使用装饰者模式之前,先了解几个重要角色。

Component(抽象构件):定义需要实现业务的抽象方法。

ConcreteComponent(具体构件):实现Component接口,用于定义具体的构建对象,可以给它增加额外的职责(方法)。

Decorator(抽象装饰类):实现Component接口,并创建Component实例对象。用于给具体构件(ConcreteComponent)增加职责。

ConcreteDecorator(具体装饰类):抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

装饰者模式UML

示例:以点餐为例,我在麦*劳点餐可以根据我需求增加食物种类和数量。

抽象构件角色:

public interface Food {
    String getDescription();
}

具体构件角色:

public class BasicSet implements Food{
    @Override
    public String getDescription() {
        return "汉堡 + 可乐";
    }
}

抽象装饰类角色:

public abstract class Decorator implements Food {

    private Food food;

    public Decorator(Food food) {
        this.food = food;
    }

    @Override
    public String getDescription() {
        return this.food.getDescription();
    }

}

具体装饰类角色:

public class FrenchFries extends Decorator {
    public FrenchFries(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 薯条";
    }
}
public class FriedChicken extends Decorator {
    public FriedChicken(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 炸鸡";
    }
}
public class IceCream extends Decorator {
    public IceCream(Food food) {
        super(food);
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " + 冰淇淋";
    }
}

测试类:

1. public class Test {
2.     public static void main(String[] args) {
3.         Food food = new BasicSet();
4.         Decorator setMealA = new FrenchFries(food);
5.         setMealA = new FrenchFries(setMealA);
6.         setMealA = new FriedChicken(setMealA);
7.         setMealA = new IceCream(setMealA);
8.         System.out.println("套餐A:" + setMealA.getDescription());
9.     }
10. }

输出结果:

套餐A:汉堡 + 可乐 + 薯条 + 薯条 + 炸鸡 + 冰淇淋
image

第3行创建基础的构件(点一份套餐,有汉堡和可乐),第4~7行分别加上需要装饰的类(还想吃两份薯条,一份炸鸡和一份冰淇淋)。由此可以看出,装饰者模式很方便的根据需求动态的改变装饰部分。

总结

不过各位有没有觉得,装饰者模式和建造者模式很相似呢?相似点都是内部把需求拼装好之后才展示出来,那什么情况下应该使用装饰者模式,什么情况下使用构建者模式呢?

装饰者模式 建造者模式
装饰物与被装饰物继承自同一组件类,组件对象均可由装饰物在外部按顺序装饰; 被建造者集成一个成员组成稳定的接口,并对成员内容做具体实现。
各装饰物记录自己装饰了谁,其功能函数除了实现自己的功能外,还需要调用被自己装饰的组件的功能函数 被创建对象的成员有一个指挥类稳定的按顺序建造,指挥类隔离建造过程及客户代码;
针对构建过程不稳定的情况 针对建造过程十分稳定的情况

了解更多设计模式:

设计模式系列

参考资料:

https://blog.csdn.net/wwwdc1012/article/details/82764333

https://www.jianshu.com/p/d7f20ae63186

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

推荐阅读更多精彩内容