1.模式动机

一般有两种方式可以实现给一个类或对象增加行为:

  • 继承机制:使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。
  • 关联机制:即将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰器(Decorator)

装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。这就是装饰模式的模式动机。

2.模式定义

装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”。

属于 对象结构型模式

3.模式结构

装饰模式主要包含以下角色:

  • 抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象。
  • 具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责。
  • 抽象装饰角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  • 具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

4.模式代码

# 抽象构建角色
public interface Component {
void operation();
} # 具体构建角色
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent operation");
}
} # 抽象装饰角色
public abstract class Decorator implements Component {
private Component component; public Decorator(Component component) {
this.component = component;
} @Override
public void operation() {
component.operation();
}
} # 具体装饰角色
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
} @Override
public void operation() {
super.operation();
doSomething();
} private void doSomething() {
System.out.println("do something");
}
} # Client
public class Client {
public static void main(String[] args) {
System.out.println("未装饰前:");
Component component = new ConcreteComponent();
component.operation(); System.out.println("装饰后:");
Decorator decorator = new ConcreteDecorator(component);
decorator.operation(); // 也可以写为
Component decoratorComponent = new ConcreteDecorator(component);
decoratorComponent.operation();
}
}

装饰前也是可以单独运行的,装饰器只是增加了新功能而已,将 component 包装了一下,增加一些新功能,然后对外提供服务。

由于 Decorator 也是 Component 的实现类,所以,可以无缝的把原先的 ConcreteComponent 类替换了,使用 ConcreteDecorator 来提供服务。

5.总结

分析

  • 与继承关系相比,关联关系的主要优势在于不会破坏类的封装性,而且继承是一种耦合度较大的静态关系,无法在程序运行时动态扩展。在软件开发阶段,关联关系虽然不会比继承关系减少编码量,但是到了软件维护阶段,由于关联关系使系统具有较好的松耦合性,因此使得系统更加容易维护。当然,关联关系的缺点是比继承关系要创建更多的对象。
  • 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。

优点

  • 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
  • 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。
  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
  • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”

缺点

  • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。
  • 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

设计模式-09装饰模式(Decorator Pattern)的更多相关文章

  1. 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern)

    原文:乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) 作者:weba ...

  2. 二十四种设计模式:装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern) 介绍动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活.示例有一个Message实体类,某个对象对它的操作有Insert()和 ...

  3. 设计模式系列之装饰模式(Decorator Pattern)——扩展系统功能

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  4. 设计模式-装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活

  5. 设计模式系列之装饰模式(Decorator Pattern)

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.这种模式创建了一个装饰类,用来包装原 ...

  6. 装饰模式(Decorator pattern)

    装饰模式(Decorator pattern): 又名包装模式(Wrapper pattern), 它以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式以对客户透明的方式动态的给 ...

  7. 基于东北F4的设计模式情景剧——第一幕 装饰模式(Decorator Pattern)

    第一场 难题未解 布景:铁岭,晴天,午后,风.在一幢还算气派的写字楼的三层外墙上,挂着一条红色横幅,上面用歪歪扭扭的毛笔字写着"东北F4软件外包工作室".大风中,那早已褪色的条幅剧 ...

  8. 设计模式09: Decorator 装饰模式(结构型模式)

    Decorator 装饰模式(结构型模式) 子类复子类,子类何其多加入我们需要为游戏中开发一种坦克,除了不同型号的坦克外,我们还希望在不同场合中为其增加以下一种多种功能:比如红外线夜视功能,比如水路两 ...

  9. 设计模式——装饰模式(Decorator Pattern)

    装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. UML图: 模型类: Component类: package com.cnblog.clarck; /** ...

随机推荐

  1. PAT甲级——1035 Password (20分)

    To prepare for PAT, the judge sometimes has to generate random passwords for the users. The problem ...

  2. TPO1-2 The Origin of Theater

    Stories (myths) may then grow up around a ritual. Frequently the myths include representatives of th ...

  3. Python数据分析与展示第3周学习笔记(北京理工大学 嵩天等)

    入门学习马上结束辽. 1.Pandas库 import pandas as pd 两个数据类型:Series,DataFrame Series类型:数据+索引 自定义索引 b = pd.Series( ...

  4. js 实现时间递增,当前时间功能,javascript格式化当天日期

    直接上代码: function nowTimeStr() {                        var date = new Date();                        ...

  5. Wanna go back home

    题目描述 Snuke lives on an infinite two-dimensional plane. He is going on an N-day trip. At the beginnin ...

  6. 4)在url中加上a分发参数,用来选哪一个函数

    文件关系目录展示: 然后代码改动部分展示: zixun.controller.class.php <?php //header('Content-type:text/html;charset=u ...

  7. 3)小案例三,加乐前端入口index.php

    之前的代码没有什么改动,唯一改动的就是我在之前的目录结构中加了  index.php作为前端的入口文件 目前,我的文件目录关系是: 然后我的index.php代码内容是: <?php /** * ...

  8. 吴裕雄--天生自然 HADOOP大数据分布式处理:安装配置Tomcat服务器

    下载链接:https://tomcat.apache.org/download-80.cgi tar -zxvf apache-tomcat-8.5.42.tar.gz -C /usr/local/s ...

  9. python去除列表中重复元素的方法

    列表中元素位置的索引用的是L.index 本文实例讲述了Python去除列表中重复元素的方法.分享给大家供大家参考.具体如下: 比较容易记忆的是用内置的set 1 2 3 l1 = ['b','c', ...

  10. Java的简易ATM系统

    大纲   ATM 机系统                   1.注册(账户(系统随机生成 15 位) - 密码(6位) - 余额)                   2.登录            ...