PHP、Python和Javascript的装饰器模式对比


Posted in PHP onFebruary 03, 2015

修饰模式(Decorator Pattern),又叫装饰者模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。装饰模式非常适用于灵活扩展对象的功能,下面是装饰模式的UML图:

PHP、Python和Javascript的装饰器模式对比

例如,有一个技术论坛,用户通过留言进行沟通,由于刚开始论坛里都是熟人,几乎都不需要对留言的内容作出审核,接收留言的页面可以是这样:

class SaveMsg(){
 private $msg;
 public function __construct($msg){
 $this->msg=$msg;
 }
 public function __store(){
 //存入数据库
 }
}

后来,随着论坛逐渐出名,就有一些人在上面发链接,就需要对含有链接的消息进行过滤,论坛进一步发展,发现除开发垃圾链接的外,还有很多无用的灌水,到后来可能还有攻击等等各种不正常的帖子,所以对论坛帖子的管理,可以单独抽象出一个类进行管理,当需要扩充过滤规则时,可以进行动态扩充。

//基类
abstract class Filter{
 abstract public function isForbid();
}
//基础过滤类
class MsgFilter extends Filter{
 public $content;
 public function __construct($msg){
 $this->content=$msg;
 }
 public function isForbid(){
 if(preg_match("/https?/i",$this->content)){
 return [true,"Not Allowed Urls"];
 }else{
 return [false];
 }
 }
}
//装饰器,用来扩充功能
abstract class FilterDecorator extends Filter{
 protected $obj;
 public function __construct(Filter $obj){
 $this->obj=$obj;
 }
}
//新过滤器,判断是否重复发帖
class repeat extends FilterDecorator{
 public function isForbid(){
 if($this->obj->isForbid()[0] === true){
 //判定是否包含url
 return $this->obj->isForbid();
 }else if($this->obj->content == "this is a test"){
 //判定是否重复发帖
 return [true,"Repeat Posts"];
 }else{
 return [false];
 }
 }
}
$test = new MsgFilter("httpsfdjoafdsajof");
print_r($test->isForbid());//被禁止
$test2 = new repeat(new MsgFilter("this is a test"));
print_r($test2->isForbid());//被禁止

在python中,不存在抽象类和方法,实现就更加简单:

#!/usr/bin/env python
class Filter():
  pass
class MsgFilter(Filter):
  def __init__(self,msg):
    self.content=msg
  def isForbid(self):
    if('http' in self.content):
      return [True,"Not Allowed Urls"]
    else:
      return [False]
class FilterDecorator(Filter):
  def __init__(self,obj):
    self._obj=obj
class Repeat(FilterDecorator):
  def isForbid(self):
    if self._obj.isForbid()[0]:
      return self._obj.isForbid()
    elif self._obj.content == 'this is a test':
      return [True,"Repeat Posts"];
    else:
      return [False]
test = MsgFilter("this is a content have http urls")
print test.isForbid()
test2 = Repeat(MsgFilter('this is a test'))
print test2.isForbid()

Javascript中,没有严格的类,所有继承都基于原型,理解起来会稍费功夫:

function MsgFilter(msg){
 this.content=msg;
 this.isForbid=function(){
 if(this.content.match(/http/g)){
 return [true,"Not Allowed Urls"];
 }else {
 return [false];
 }
 }
}
function Repeat(obj){
 var _obj=obj;
 this.isForbid=function(){
 if(_obj.isForbid[0] === true){
 return _obj.isForbid();
 }else if(_obj.content=='this is a test'){
 return [true,"Repeat Posts"];
 }else{
 return [false];
 }
 }
}
var test = new MsgFilter("his is a content have http urls");
console.log(test.isForbid());
var test2 = new Repeat(new MsgFilter("this is a test"));
console.log(test2.isForbid());

由于Javascript缺少类的特性,继承对于它来说就显得有点鸡肋了,上面的代码看起来更像是对两个函数的处理, 在python中,有更加简单的添加装饰器的方法,直接通过”@”给函数自动添加装饰器,达到扩展功能的目的,如:

def Decorator(F):
  def newF(age):
    print "You Are Calling",F.__name__
    F(age)
  return newF
@Decorator
#通过@给函数showAge添加装饰器Decorator
def showAge(age):
  print "hello , i am %d years old"%age
showAge(10)

装饰模式的目的是解决动态扩展功能的难题,装饰模式的本质是对对象的灵活处理,理解装饰模式,不仅能深入了解面向对象的程序设计,更能提高编程的思维能力。

PHP 相关文章推荐
用PHP中的 == 运算符进行字符串比较
Nov 26 PHP
php多文件上传实现代码
Feb 20 PHP
php数组合并array_merge()函数使用注意事项
Jun 19 PHP
PHP实现加强版加密解密类实例
Jul 29 PHP
验证token、回复图文\文本、推送消息的实用微信类php代码
Jun 28 PHP
Yii2创建控制器(createController)方法详解
Jul 23 PHP
浅析Laravel5中队列的配置及使用
Aug 04 PHP
PHP实现生成带背景的图形验证码功能
Oct 03 PHP
PHP 实现公历日期与农历日期的互转换
Sep 13 PHP
Windows上php5.6操作mongodb数据库示例【配置、连接、获取实例】
Feb 13 PHP
PHP使用 Imagick 扩展实现图片合成,圆角处理功能示例
Sep 09 PHP
PHP实现随机发放扑克牌
Apr 21 PHP
php对象在内存中的存在形式分析
Feb 03 #PHP
浅析THINKPHP的addAll支持的最大数据量
Feb 03 #PHP
php格式化金额函数分享
Feb 02 #PHP
php可应用于面包屑导航的迭代寻找家谱树实现方法
Feb 02 #PHP
php生成唯一的订单函数分享
Feb 02 #PHP
php数组去除空值函数分享
Feb 02 #PHP
php截取字符串函数分享
Feb 02 #PHP
You might like
php curl登陆qq后获取用户信息时证书错误
2015/02/03 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
2016/09/23 PHP
php字符串操作常见问题小结
2016/10/11 PHP
ASP 过滤数组重复数据函数(加强版)
2010/05/31 Javascript
js字符编码函数区别分析
2011/12/28 Javascript
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
JS实现同一个网页布局滑动门和TAB选项卡实例
2015/09/23 Javascript
node.JS md5加密中文与php结果不一致的解决方法
2017/05/05 Javascript
浅谈vue中.vue文件解析流程
2018/04/24 Javascript
微信小程序签到功能
2018/10/31 Javascript
javascript实现前端分页效果
2020/06/24 Javascript
详解webpack的clean-webpack-plugin插件报错
2020/10/16 Javascript
JavaScript 实现继承的几种方式
2021/02/19 Javascript
[01:30:54]《加油DOTA》 第三期
2014/08/18 DOTA
[35:39]完美世界DOTA2联赛PWL S2 FTD.C vs Rebirth 第二场 11.22
2020/11/24 DOTA
python中的lambda表达式用法详解
2016/06/22 Python
python selenium UI自动化解决验证码的4种方法
2018/01/05 Python
谈一谈数组拼接tf.concat()和np.concatenate()的区别
2020/02/07 Python
Python中logger日志模块详解
2020/08/04 Python
python 基于opencv实现高斯平滑
2020/12/18 Python
详解CSS3中字体平滑处理和抗锯齿渲染
2017/03/29 HTML / CSS
英超联赛的首选足球:Mitre足球
2019/05/06 全球购物
MAC彩妆澳洲官网:M·A·C AU
2021/01/17 全球购物
枚举和一组预处理的#define有什么不同
2016/09/21 面试题
什么是"引用"?申明和使用"引用"要注意哪些问题?
2016/03/03 面试题
护士自我鉴定
2013/10/23 职场文书
护士自荐信范文
2013/12/15 职场文书
中英文自我评价常用句型
2013/12/19 职场文书
入党自我评价优缺点
2014/01/25 职场文书
励志演讲稿3分钟
2014/08/21 职场文书
淘宝好评语句大全
2014/12/31 职场文书
客户答谢会致辞
2015/01/20 职场文书
患者身份识别制度
2015/08/06 职场文书
OpenCV中resize函数插值算法的实现过程(五种)
2021/06/05 Python
AJAX实现指定部分页面刷新效果
2021/10/16 Javascript
教你使用Jenkins集成Harbor自动发布镜像
2022/04/03 Servers