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 12 PHP
php自动获取目录下的模板的代码
Aug 08 PHP
那些年一起学习的PHP(一)
Mar 21 PHP
PHP时间戳 strtotime()使用方法和技巧
Oct 29 PHP
PHP获取浏览器信息类和客户端地理位置的2个方法
Apr 24 PHP
PHP实现即时输出、实时输出内容方法
May 27 PHP
DEDECMS首页调用图片集里的多张图片
Jun 05 PHP
简单PHP会话(session)说明介绍
Aug 21 PHP
PHP单元测试框架PHPUnit用法详解
Jan 23 PHP
PHP随机数函数rand()与mt_rand()的讲解
Mar 25 PHP
php实现微信小程序授权登录功能(实现流程)
Nov 13 PHP
php引用传递
Apr 01 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获取搜索引擎关键字来源的函数(支持百度和谷歌等搜索引擎)
2012/10/03 PHP
php导出word格式数据的代码实例
2013/11/25 PHP
查找php配置文件php.ini所在路径的二种方法
2014/05/26 PHP
php匹配字符中链接地址的方法
2014/12/22 PHP
php使用GD2绘制几何图形示例
2017/02/15 PHP
PHP的反射机制实例详解
2017/03/29 PHP
php 使用curl模拟ip和来源进行访问的实现方法
2017/05/02 PHP
有关PHP 中 config.m4 的探索
2020/08/26 PHP
js实现iframe动态调整高度的代码
2008/01/06 Javascript
js以对象为索引的关联数组
2010/07/04 Javascript
jQuery学习笔记 更改jQuery对象
2012/09/19 Javascript
JavaScript对象学习经验整理
2013/10/12 Javascript
jQuery实现简单的日期输入格式化控件
2015/03/12 Javascript
js实现鼠标划过给div加透明度的方法
2015/05/25 Javascript
JavaScript实现将UPC转换成ISBN的方法
2015/05/26 Javascript
JavaScript解八皇后问题的方法总结
2016/06/12 Javascript
AngularJS 获取ng-repeat动态生成的ng-model值实例详解
2016/11/29 Javascript
jquery插入兄弟节点的操作方法
2016/12/07 Javascript
微信小程序 wepy框架与iview-weapp的用法详解
2019/04/10 Javascript
Vue 自适应高度表格的实现方法
2020/05/13 Javascript
vue 中的动态传参和query传参操作
2020/11/09 Javascript
[02:51]DOTA2 2015国际邀请赛中国区预选赛第一日战报
2015/05/27 DOTA
[52:02]完美世界DOTA2联赛PWL S2 FTD.C vs SZ 第一场 11.27
2020/11/30 DOTA
详解Python中的元组与逻辑运算符
2015/10/13 Python
tensorflow训练中出现nan问题的解决
2018/02/10 Python
pycharm运行出现ImportError:No module named的解决方法
2018/10/13 Python
python使用pandas处理大数据节省内存技巧(推荐)
2019/05/05 Python
人力资源管理专业毕业生推荐信
2013/11/07 职场文书
大学生职业生涯规划书模板
2014/01/03 职场文书
销售总监岗位职责
2014/01/04 职场文书
美术教学感言
2014/02/22 职场文书
2014年副班长工作总结
2014/12/10 职场文书
值班管理制度范本
2015/08/06 职场文书
CSS实现渐变色边框(Gradient borders)的5种方法
2022/03/25 HTML / CSS
SpringBoot整合Minio文件存储
2022/04/03 Java/Android
flex布局中使用flex-wrap实现换行的项目实践
2022/06/21 HTML / CSS