简介

场景

通过继承和关联都可以给对象增加行为,区别如下:

  • 继承是静态的(无法在程序运行时动态扩展),且作用于所有子类。硬编码,高耦合。
  • 通过装饰器可以在运行时添加行为和属性到指定对象。关联关系就是在一个类中嵌入另一个类的对象,被嵌入的对象就是装饰器。可以动态决定是否调用这个内嵌对象,低耦合。

模式定义

装饰模式:动态地给指定对象增加额外职责。

装饰模式对客户透明,可以嵌套执行多次装饰,顺序不影响结果。

就增加对象功能来说,装饰模式(关联关系)比继承和实现这两种关系更为灵活。

模式特点

装饰模式包含 4 种角色:

  • Component:抽象构件
  • ConcreteComponent:具体构件
  • Decorator:抽象装饰类
  • ConcreteDecorator:具体装饰类

优缺点

优点:

  • 装饰模式可以动态扩展一个对象的功能,可以在运行时通过配置文件选择不同的装饰器,从而实现不同的行为
  • 装饰类可以排列组合,创造出很多不同行为的组合
  • 装饰类扩展时,原有代码无须改变,符合“开闭原则”

缺点:

  • 使用装饰模式进行系统设计时将产生很多小对象,每个对象仅负责一部分装饰任务
  • 多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐

PHP 代码示例

下面例子中,通过不同的装饰器类对标题进行不同的操作:

<?php

class Book {
private $title;
private $author; public function __construct($title, $author) {
$this->title = $title;
$this->author = $author;
} public function getTitle() {
return $this->title;
}
} class TitleDecorator {
protected $book;
protected $title; public function __construct(Book $book) {
$this->book = $book;
$this->resetTitle();
} public function resetTitle() {
$this->title = $this->book->getTitle();
} public function showTitle() {
return $this->title;
}
} class TitleStarDecorator extends TitleDecorator {
private $titleDecorator; public function __construct(TitleDecorator $td) {
$this->titleDecorator = $td;
} public function starTitle() {
$this->titleDecorator->title = str_replace(" ","*",$this->titleDecorator->title);
}
} class TitleQuoteDecorator extends TitleDecorator {
private $titleDecorator; public function __construct(TitleDecorator $td) {
$this->titleDecorator = $td;
} public function quoteTitle() {
$this->titleDecorator->title = "《".$this->titleDecorator->title."》";
}
} $book = new Book("a good world", "Lu Xun");
$td = new TitleDecorator($book);
$tsd = new TitleStarDecorator($td);
$tqd = new TitleQuoteDecorator($td); function write_ln($str) {
echo $str.PHP_EOL.'<br/>';
} write_ln($book->getTitle());
$tsd->starTitle();
write_ln($td->showTitle()); $tqd->quoteTitle();
write_ln($td->showTitle()); $tqd->quoteTitle();
write_ln($td->showTitle());

输出如下:

a good world
a*good*world
《a*good*world》
《《a*good*world》》

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

  1. 说说设计模式~装饰器模式(Decorator)~多功能消息组件的实现

    返回目录 为何要设计多功能消息组件 之前写过一篇装饰器模式的文章,感觉不够深入,这次的例子是实现项目中遇到的,所以把它拿出来,再写写,之前也写过消息组件的文章,主要采用了策略模式实现的,即每个项目可以 ...

  2. 说说设计模式~装饰器模式(Decorator)

    返回目录 装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序, ...

  3. 设计模式(八)装饰器模式Decorator(结构型)

    设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法 ...

  4. 【PHP设计模式 09_ZhuangShiQi.php】装饰器模式 (decorator)

    <?php /** * [装饰器模式 (decorator)] * 有时候发布一篇文章需要经过很多人手,层层处理 */ header("Content-type: text/html; ...

  5. JAVA设计模式--装饰器模式

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

  6. 装饰器模式-Decorator(Java实现)

    装饰器模式-Decorator(Java实现) 装饰器模式允许向一个现有的对象添加新的功能, 同时又不改变其结构. 其中 "现有对象"在本文中是StringDisplay类. 添加 ...

  7. 装饰器模式 Decorator 结构型 设计模式 (十)

    引子           现实世界的装饰器模式 大家应该都吃过手抓饼,本文装饰器模式以手抓饼为模型展开简介 "老板,来一个手抓饼,  加个培根,  加个鸡蛋,多少钱?" 这句话会不 ...

  8. 设计模式学习心得<装饰器模式 Decorator>

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

  9. 23种设计模式之装饰器模式(Decorator Pattern)

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

  10. python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

随机推荐

  1. Mysql UPF 安装文档

    一.mysql UDF 简介: github地址: http://www.mysqludf.org/lib_mysqludf_preg 二.mysql UDF 下载地址: https://github ...

  2. Ubuntu 12.04安装Gitlab及问题解决

    最近看了下Git,并且之前听同学说过gitlab这个东西,就想自己也搭建一个gitlab,做一个像github那样的代码管理站点,现在的gitlab要安装确实是非常非常方便, https://abou ...

  3. python为什么人们喜欢学习呢?

    软件的质和量. 既有量的积累也有质的区别.继承一定的前人研究基础. 基本上来说,python更加的注重可读性,一致性,可移植性,其中软件的质量也是比较的讲究的. python支持开发的高级重用机制,例 ...

  4. Vue.js状态管理模式 Vuex

    vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 安装.使用 vuex 首先我们在 vue. ...

  5. django信号相关

    Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者. 1.Django内置信号 Model signals pre_in ...

  6. vue动态生成表单

    vue动态生成表单 一.下拉框 <!DOCTYPE html> <html> <head> <meta charset="utf-8" / ...

  7. 【转】C/C++产生随机数

    转自:https://www.cnblogs.com/vectors07/p/8185215.html C/C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,C语言/C++里 ...

  8. 吉首大学2019年程序设计竞赛(重现赛)I 滑稽树上滑稽果 (莫队+逆元打表)

    链接:https://ac.nowcoder.com/acm/contest/992/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K  ...

  9. navicat的使用(测试库和正式库同步)以及用plsql改表字段属性

    说明:数据库的操作,除了查询,最好先做好备份,比如数据同步.更新.修改或删除之类的: netstat -antp   查看mysql端口 firewall -cmd --list-all    查看防 ...

  10. ECS 按量付费转包年包月支持按周啦

    功能场景 不需要别的理由,就是省钱. 以 华北1 ecs.t5-c1m2.xlarge ( 4vCPU 8GB ) 为例:按量付费一周需要 131元,而按周付费只需要 68元. 如果您正在使用按量付费 ...