设计模式:装饰器模式介绍和应用

简短描述

当前有一个功能完善的对象,如果我们想要给这个对象添加一个新的职责,那么我们可以用一个新的类去装饰它来实现对原有对象职责的扩展。新的类称为“装饰者”,原有的对象称为“被装饰者”。这种模式被称为装饰器模式。

现实生活中的装饰器模式

装饰器模式在现实生活中的例子简直太多了。比如我开了一个奶茶店,卖的是普通的奶茶。现在我想引入一个叫珍珠奶茶的商品,我要怎么做呢?

我是不是需要升级一下我的制作奶茶的机器,让它支持珍珠奶茶的做法?但这种成本估计比较高,说不定还没原来做奶茶的机器好用呢!实际上我只需要买一个能做“珍珠”的机器就行!把“珍珠”放进奶茶不就成了珍珠奶茶。原有的做奶茶的机器依然可以稳定地制作做奶茶,也避免花成本去学习操作新的机器。

在这个案例中,珍珠就是装饰者,奶茶就是被装饰者。

很容易就写出一个上面所描述的装饰器模式的代码。 首先定义一个饮料接口

interface Drink
{
    public function getPrice();
}

我们现在已经在卖奶茶了,下面是一个奶茶的类。价格已经订好了,10元!

class MilkTea implements Drink
{
    public function getPrice()
    {
        return 10;
    }
}

接着有一个新的品种,叫珍珠奶茶,我只要写一个珍珠的类,然后装饰一下奶茶,这个奶茶就成了珍珠奶茶。

class Boba implements Drink
{
    public function __construct($MilkTea)
    {
        $this->MilkTea = $MilkTea;
    }

    public function getPrice()
    {
        return $this->MilkTea->getPrice() + 5;
    }
}

看看珍珠奶茶是怎么制造出来的

// 先把奶茶做出来
$MilkTea = new MilkTea();
// 用珍珠去装饰这个奶茶,变成了波霸奶茶
$Boba = new Boba($MilkTea);
// 看看现在波霸奶茶的价格
echo $Boba->getPrice();

装饰模式使用起来还是非常容易的。在实际应用中,装饰器模式使用场景也十分广泛。

装饰器应用场景一:参数验证

api中参数验证是必不可少的,我们会选择一些已经很成熟的参数验证器,假如现在有一个非常成熟的参数验证器叫validator,我们现在用的也非常好。

突然有一天,一个需求说接口需要增加一个签名验证,然而现有的验证器不支持该功能,怎么解决呢?

第一反应可能是直接修改这个验证器,让其增加签名验证功能,但这样可不是个很好的解决方案。一个是直接修改会引入风险,一个是如果后续有更多需求,这个稳定的验证器可能会被改的一团糟,还有就是增加一个业务的需求可能让这个验证器变得有点“多事”了…

这个时候装饰器就派上用场了,不修改原有的验证器,用一个新的验证器去装饰原有的验证器就好啦!新的验证器就是为当前业务定制的专有验证器,而原来的验证器也保持了它只该有的功能。

装饰器应用场景二:日志记录

现在有一个使用了很久的日志记录类,代码写的还行,使用也很稳定,但是功能比较单一,仅仅是把日志写入一个文件就完事了。

我突发奇想想让这个日志类能够自动实现根据日期归档,这个时候我就可以写一个装饰器,这个装饰器实现了文件归档的功能,去装饰日志记录类,装饰之后的日志记录类就成为了一个带有文件归档的日志记录类。

你可能还喜欢下面这些文章

linux文件描述符介绍

文件描述符是什么文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。习惯上,标准输入(standard input)的文件描述符是 0,标准输出(standard output)是 1,标准错误(standard error)是 2。尽管这种习惯并非Unix内核的特性,但是因为一些 shell 和很多应用程序都使用这种习惯,因此,如

设计模式:观察者模式介绍与应用场景

简短描述在观察者模式中,有一个主题和几个观察者,主题状态改变之后会通知到所有的观察者。现实中的观察者模式观察者模式和现实世界很好对应。比如我和我的朋友们购买了今年一年的报纸,每次报社印刷了今天的报纸之后就会往我这里送。在这个系统里面,“报社“是一个主题,“我和我的朋友们”就是一个观察者,当“报社”生产报纸之后,“我和我的朋友们”都能收到这份报纸。根据上面的描述,我们很容易写出一个观察者模式。首先定义一个报社作为主题,然后定义一些用户作为观察者。不过在此之前,我们先定义主题和观察者的接口,毕竟我们是面向接口编程。定义一个主题接口namespace ds\observer\contract;/**

介绍一款工具,memcacheadmin,使用php制作的memcached管理监控工具

MemAdmin是一款可视化的Memcached管理与监控工具,使用PHP开发,体积小,操作简单。主要功能: 服务器参数监控:STATS、SETTINGS、ITEMS、SLABS、SIZES实时刷新 服务器性能监控:GET、DELETE、INCR、DECR、CAS等常用操作命中率实时监控 支持数据遍历,方便对存储内容进行监视 支持条件查询,筛选出满足条件的KEY或VALUE 数组、JSON等序列化字符反序列显示 兼容memcache协议的其他服务,如Tokyo Tyrant (遍历功能除外) 支持服务器连接池,多服务器管理切换方便简洁guthub地址:https://github.com/ju

布隆过滤器(bloom filter)介绍以及php和redis实现布隆过滤器实现方法

引言在介绍布隆过滤器之前我们首先引入几个场景。场景一在一个高并发的计数系统中,如果一个key没有计数,此时我们应该返回0。但是访问的key不存在,相当于每次访问缓存都不起作用了。那么如何避免频繁访问数量为0的key而导致的缓存被击穿?有人说, 将这个key的值置为0存入缓存不就行了吗?这是确实是一种解决方案。当访问一个不存在的key的时候,设置一个带有过期时间的标志,然后放入缓存。不过这样做的缺点也很明显:浪费内存和无法抵御随机key攻击。场景二在一个黑名单系统中,我们需要设置很多黑名单内容。比如一个邮件系统,我们需要设置黑名单用户,当判断垃圾邮件的时候,要怎么去做。比如爬虫系统,我们要记录下

赞赏

微信赞赏支付宝赞赏

《设计模式:装饰器模式介绍和应用》有1条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注