5分钟读懂设计模式(2)---装饰者模式

每当我们买了新房子之后,相信绝大部分人都会进行装修,给房子增加一些其他新的物品。不过,无论如何装修,这个房子还是这个房子,最本质的东西并没有变,有的只是我们通过装修的方式,给这个房子增加了一些额外的功能.....

通过装修的方式,给房子增加一些我们想要的额外功能,这种方式,就类似于我们今天要讲的设计模式:装饰者模式

1.装饰模式概念

装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。例如上面的房子装修,我们买了手机之后给手机装上手机壳,贴上手机膜等。这些,都可以说是装修模式的应用。

不过这里需要注意的是,装修模式与继承不一样,继承是需要一个子类来拓展对象的功能,而装饰模式则不一样,它是通过定义一个装饰类,在这个装饰类中持有某些对象的引用,然后通过使用对象之间的关联关系来取代类之间的继承关系。

2.定义

装饰模式(Decorator Pattern):在不必改变原类文件和原类使用的继承的情况下,动态地扩展一个对象的功能。就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式

角色

和观察者模式类似,观察者模式一般会有如下四个角色:

  1. 抽象构件(Component).
  2. 具体构件(ConcreteComponet)。
  3. 抽象装饰类(Decorator)。
  4. 具体装饰类(ConcreteDecorator)。

下面介绍下四个角色的一些功能、任务。

  1. 抽象构件:它是具体构件和抽象装饰类的共同父类,声明了要在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象。抽象构件一般定义为接口
  2. 具体构件:它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰对象可以给它增加额外的职责(方法)。
  3. 抽象装饰类:它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
  4. 具体装饰类:它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

下面我给个例子吧,看个例子就比较知道这些角色都是个什么情况了。

3.例子

在n年前,人类捕捉了动物之后,会直接杀了之后就拿来吃,而不会把它烤熟、弄上一些配料之后再吃。但是到了后来,人类就懂得了把动物烤熟、弄上配料之后再吃了。

现在我们假设人类本来是不会烤熟之后再吃的,而是被装饰了一些额外的能力之后,才知道烤熟之后再吃。(貌似这个例子有点勉强.....)。

现在开始定义上面那四个角色:

1.抽象构件

/**
 * 定义作为人类应有的一些规范
 */
public interface Human {
    void eating();
}

2.具体构件

/**
 * 具体构件类
 */
public class Man implements Human{
    @Override
    public void eating() {
        System.out.println("吃刚刚捕获的美味佳肴");
    }
}

3.抽象装饰类

/**
 * 抽象装饰者,需要实现抽象构件接口
 */
public class Decorator implements Human{
    //维持对抽象构件的引用
    private Human human;
    //注入构件实例
    public Decorator(Human human) {
        this.human = human;
    }

    @Override
    public void eating() {
        human.eating();
    }
}

注意: 在Decorator中并未真正实现eat()方法,而只是调用原有Human对象的eating()方法,它没有真正实施装饰,而是提供一个统一的接口,将具体装饰过程交给子类完成。

4.具体装饰类

public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Human human){
        super(human);
    }

    @Override
    public void eating() {
        System.out.println("把捕捉的动物给烤熟了,在加些配料");
        super.eating();
        System.out.println("吃完饭之后洗手");
    }
    //需要增加的其他方法
}

5.测试类

public class Demo {
    public static void main(String[] args){
        Human man = new Man();
        //没进行装饰之前
        man.eating();
        System.out.println("--------------------");
        //进行装饰之后
        man = new ConcreteDecorator(man);
        man.eating();
    }
}

6.打印结果

吃刚刚捕获的美味佳肴
--------------------
把捕捉的动物给烤熟了,在加些配料
吃刚刚捕获的美味佳肴
吃完饭之后洗手

从这个简单的例子可以看到,没有并没有改变原来的Man类,同时也没有定义他的子类来进行功能的拓展,而是通过一个装饰类的辅助来实现Man类功能的增强,这就是装饰者模式的作用。

优缺点

优点:

1,使用装饰者模式比使用继承更加灵活,因为它选择通过一种动态的方式来扩展一个对象的功能,在运行时可以选择不同的装饰器,从而实现不同的行为。

2,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。

3,具体构件类与具体装饰类可以独立变化,他能是低耦合的。用户可以根据需要来增加新的具体构件类和具体装饰类,在使用时再对其进行各种组合,原有代码无须改变,符合“开闭原则”。

缺点:

1,会产生很多的小对象,增加了系统的复杂性

2,由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。

参考资料:

  1. 设计模式java版。
  2. Head First设计模式

关注公我的众号:苦逼的码农,获取更多原创文章,后台回复礼包送你一份时下热门的资源大礼包。同时也感谢把文章介绍给更多需要的人

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

推荐阅读更多精彩内容

  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 3,734评论 0 14
  • 【学习难度:★★★☆☆,使用频率:★★★☆☆】直接出处:装饰模式梳理和学习:https://github.com/...
    BruceOuyang阅读 709评论 2 2
  • 参考资料:菜鸟教程之设计模式 设计模式概述 设计模式(Design pattern)代表了最佳的实践,通常被有经验...
    Steven1997阅读 1,163评论 1 12
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,895评论 1 15
  • 第一天 我有没有负债?负债的对象是谁?在今天,给你的债主发一个红包,红包大小可以自己决定,感谢对方曾经愿意借钱给你...
    親文文俪阅读 287评论 0 1