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&&mysql)三
Oct 09 PHP
基于mysql的论坛(5)
Oct 09 PHP
php minixml详解
Jul 19 PHP
php面向对象全攻略 (九)访问类型
Sep 30 PHP
PHP验证码类代码( 最新修改,完全定制化! )
Dec 02 PHP
如何使用php绘制在图片上的正余弦曲线
Jun 08 PHP
PHP保存session到memcache服务器的方法
Jan 19 PHP
Ubuntu VPS中wordpress网站打开时提示”建立数据库连接错误”的解决办法
Nov 03 PHP
PHP获取当前执行php文件名的代码
Mar 02 PHP
降低PHP Redis内存占用
Mar 23 PHP
PHP中单例模式的使用场景与使用方法讲解
Mar 18 PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
Sep 30 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开发框架总结收藏
2008/04/24 PHP
PHP有序表查找之插值查找算法示例
2018/02/10 PHP
PHP中单例模式的使用场景与使用方法讲解
2019/03/18 PHP
Yii Framework框架使用PHPExcel组件的方法示例
2019/07/24 PHP
PHP之多条件混合筛选功能的实现方法
2019/10/09 PHP
imagettftext() 失效,不起作用
2021/03/09 PHP
jQuery动画效果图片轮播特效
2016/01/12 Javascript
禁用backspace网页回退功能的实现代码
2016/11/15 Javascript
微信小程序 限制1M的瘦身技巧与方法详解
2017/01/06 Javascript
详解webpack自动生成html页面
2017/06/29 Javascript
给vue项目添加ESLint的详细步骤
2017/09/29 Javascript
vue+iview 实现可编辑表格的示例代码
2018/10/31 Javascript
优化Vue项目编译文件大小的方法步骤
2019/05/27 Javascript
解决layui 表单元素radio不显示渲染的问题
2019/09/04 Javascript
vue使用axios实现excel文件下载的功能
2020/07/16 Javascript
javascript运行机制之执行顺序理解
2020/08/03 Javascript
jQuery实现简单轮播图效果
2020/12/27 jQuery
python中的多重继承实例讲解
2014/09/28 Python
flask框架jinja2模板与模板继承实例分析
2019/08/01 Python
Django实现将一个字典传到前端显示出来
2020/04/03 Python
pycharm激活方法到2099年(激活流程)
2020/09/22 Python
谈一谈HTML5本地存储技术
2016/03/02 HTML / CSS
详解HTML5如何使用可选样式表为网站或应用添加黑暗模式
2020/04/07 HTML / CSS
欧洲品牌瓷器餐具网上商店:Porzellantreff.de
2018/04/04 全球购物
英国领先的隐形眼镜在线供应商:Lenstore.co.uk
2019/11/24 全球购物
Kendra Scott官网:美国领先的时尚配饰品牌
2020/10/22 全球购物
银行见习期自我鉴定
2014/01/29 职场文书
校庆活动方案
2014/03/31 职场文书
啦啦队口号大全
2014/06/16 职场文书
银行竞聘上岗演讲稿
2014/09/12 职场文书
住房抵押登记委托书
2014/09/27 职场文书
党员剖析材料范文
2014/09/30 职场文书
学校总务处领导干部个人对照检查材料思想汇报
2014/10/06 职场文书
六查六看个人剖析材料
2014/10/14 职场文书
教师党员批评与自我批评
2014/10/15 职场文书
保险公司客户经理岗位职责
2015/04/09 职场文书