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 相关文章推荐
第一节--面向对象编程
Nov 16 PHP
Zend Framework中的简单工厂模式 图文
Jul 10 PHP
解析php中die(),exit(),return的区别
Jun 20 PHP
解析web文件操作常见安全漏洞(目录、文件名检测漏洞)
Jun 29 PHP
destoon二次开发常用数据库操作
Jun 21 PHP
ThinkPHP实现一键清除缓存方法
Jun 26 PHP
PHP生成器简单实例
May 13 PHP
PHP版本常用的排序算法汇总
Dec 20 PHP
PHP实现判断数组是一维、二维或几维的方法
Feb 06 PHP
php中时间函数date及常用的时间计算
May 12 PHP
PHP图片水印类的封装
Jul 06 PHP
PHP将数据导出Excel表中的实例(投机型)
Jul 31 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
人尽可用的Windows技巧小贴士之下篇
2007/03/22 PHP
通过PHP current函数获取未知字符键名数组第一个元素的值
2013/06/24 PHP
PHP函数shuffle()取数组若干个随机元素的方法分析
2016/04/02 PHP
PHP创建XML的方法示例【基于DOMDocument类及SimpleXMLElement类】
2019/09/10 PHP
php字符串函数 str类常见用法示例
2020/05/15 PHP
PHP如何防止用户重复提交表单
2020/12/09 PHP
文本加密解密
2006/06/23 Javascript
最简单的jQuery程序 入门者学习
2009/07/09 Javascript
按给定几率进行随机抽取的js代码
2010/12/28 Javascript
JS中的substring和substr函数的区别说明
2013/05/07 Javascript
Node.js模拟浏览器文件上传示例
2014/03/26 Javascript
浅谈重写window对象的方法
2014/12/29 Javascript
js实现不重复导入的方法
2016/03/02 Javascript
laydate日历控件使用方法详解
2017/11/20 Javascript
NodeJS加密解密及node-rsa加密解密用法详解
2018/10/12 NodeJs
实例讲解JavaScript截取字符串
2018/11/30 Javascript
vue vantUI tab切换时 list组件不触发load事件的问题及解决方法
2020/02/14 Javascript
Python实现一个简单的MySQL类
2015/01/07 Python
简单介绍Ruby中的CGI编程
2015/04/10 Python
Python内建函数之raw_input()与input()代码解析
2017/10/26 Python
Django实现支付宝付款和微信支付的示例代码
2018/07/25 Python
python实现抖音点赞功能
2019/04/07 Python
keras 使用Lambda 快速新建层 添加多个参数操作
2020/06/10 Python
解决Keras中Embedding层masking与Concatenate层不可调和的问题
2020/06/18 Python
Pythonic版二分查找实现过程原理解析
2020/08/11 Python
Python下使用Trackbar实现绘图板
2020/10/27 Python
Electrolux伊莱克斯巴西商店:家用电器、小家电和配件
2018/05/23 全球购物
Roxy俄罗斯官方网站:冲浪和滑雪板的一切
2020/06/20 全球购物
老师给学生的表扬信
2014/01/17 职场文书
产品生产计划书
2014/05/07 职场文书
2014乡镇党委副书记对照检查材料思想汇报
2014/10/09 职场文书
《折线统计图》教学反思
2016/02/22 职场文书
写作之关于描写老人的好段摘抄
2019/11/14 职场文书
python 下划线的多种应用场景总结
2021/05/12 Python
世界无敌的ICOM IC-R9500宽频接收机
2022/03/25 无线电
Android开发手册TextInputLayout样式使用示例
2022/06/10 Java/Android