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注入点构造代码
Jun 14 PHP
php 图片加水印与上传图片加水印php类
May 12 PHP
PHP实现多条件查询实例代码
Jul 17 PHP
php FLEA中二叉树数组的遍历输出
Sep 26 PHP
php 删除目录下N分钟前创建的所有文件的实现代码
Aug 10 PHP
理解PHP中的stdClass类
Apr 18 PHP
WIN8.1下搭建PHP5.6环境
Apr 29 PHP
Thinkphp模板标签if和eq的区别和比较实例分析
Jul 01 PHP
Yii模型操作之criteria查找数据库的方法
Jul 15 PHP
PHP全功能无变形图片裁剪操作类与用法示例
Jan 10 PHP
轻松实现php文件上传功能
Feb 17 PHP
PHP的imageTtfText()函数深入详解
Mar 03 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 代码优化之经典示例
2011/03/24 PHP
php跨站攻击实例分析
2014/10/28 PHP
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2611816 bytes)
2014/11/08 PHP
JavaScript 动态改变图片大小
2009/06/11 Javascript
javascript自动改变文字大小和颜色的效果的小例子
2013/08/02 Javascript
jquery动态增加删除表格行的小例子
2013/11/14 Javascript
jquery改变tr背景色的示例代码
2013/12/28 Javascript
图片翻转效果具体实现代码
2014/01/09 Javascript
chrome下img加载对height()的影响示例探讨
2014/05/26 Javascript
javascript 动态创建表格的2种方法总结
2015/03/04 Javascript
实现前后端数据交互方法汇总
2015/04/07 Javascript
跟我学习javascript的垃圾回收机制与内存管理
2015/11/23 Javascript
AngularJs动态加载模块和依赖注入详解
2016/01/11 Javascript
浅谈JavaScript中面向对象的的深拷贝和浅拷贝
2016/08/01 Javascript
vue.js入门教程之基础语法小结
2016/09/01 Javascript
JSON对象 详解及实例代码
2016/10/18 Javascript
vue2单元测试环境搭建
2018/05/24 Javascript
vue axios数据请求get、post方法及实例详解
2018/09/11 Javascript
JavaScript之解构赋值的理解
2019/01/30 Javascript
vue选项卡切换登录方式小案例
2019/09/27 Javascript
[03:01]2014DOTA2国际邀请赛 小组赛7月13日TOPPLAY
2014/07/14 DOTA
Python的标准模块包json详解
2017/03/13 Python
HTML5 UTF-8 中文乱码的解决方法
2013/11/18 HTML / CSS
Html5基于canvas实现电子签名并生成PDF文档
2020/12/07 HTML / CSS
亚瑟士美国官网:ASICS美国
2017/02/01 全球购物
墨西哥皇宫度假村预订:Palace Resorts
2018/06/16 全球购物
乌克兰珠宝大卖场:Zlato.ua
2020/09/27 全球购物
华硕新加坡官方网上商店:ASUS Singapore
2020/07/09 全球购物
PHP开发的一般流程
2013/08/13 面试题
Java面试题:Java类的Main方法如果是Private将会怎么样
2016/08/18 面试题
小学生优秀评语大全
2014/04/22 职场文书
大学英语专业求职信
2014/06/21 职场文书
2014年纪委工作总结
2014/12/05 职场文书
销售员岗位职责范本
2015/04/11 职场文书
公司职员入党自传书
2015/06/26 职场文书
表彰大会新闻稿
2015/07/17 职场文书