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中使用sockets:从新闻组中获取文章
Oct 09 PHP
smarty巧妙处理iframe中内容页的代码
Mar 07 PHP
用PHP读取超大文件的实例代码
Apr 01 PHP
php判断变量类型常用方法
Apr 24 PHP
PHP 下载文件时自动添加bom头的方法实例
Jan 10 PHP
php实现aes加密类分享
Feb 16 PHP
MyEclipse常用配置图文教程
Sep 11 PHP
PHP与MYSQL中UTF8编码的中文排序实例
Oct 21 PHP
php+ajax实现无刷新数据分页的办法
Nov 02 PHP
WordPress中用于获取搜索表单的PHP函数使用解析
Jan 05 PHP
Yii2框架引用bootstrap中日期插件yii2-date-picker的方法
Jan 09 PHP
php简单检测404页面的方法示例
Aug 23 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
日本十大科幻动漫 宇宙骑士垫底,第一已成经典
2020/03/04 日漫
采用header定义为文件然后readfile下载(隐藏下载地址)
2014/01/31 PHP
ThinkPHP框架实现session跨域问题的解决方法
2014/07/01 PHP
PHP连接SQLServer2005的方法
2015/01/27 PHP
Yii2中简单的场景使用介绍
2017/06/02 PHP
Jquery实战_读书笔记1—选择jQuery
2010/01/22 Javascript
js绑定事件this指向发生改变的问题解决方法
2013/04/23 Javascript
jquery实现两个图片渐变切换效果的方法
2015/06/25 Javascript
js实现的星星评分功能函数
2015/12/09 Javascript
微信小程序 开发经验整理
2017/02/15 Javascript
使用node.js对音视频文件加密的实例代码
2017/08/30 Javascript
ES6中的Promise代码详解
2017/10/09 Javascript
node 命令方式启动修改端口的方法
2018/05/12 Javascript
angularjs $http调用接口的方式详解
2018/08/13 Javascript
js实现按钮开关单机下拉菜单效果
2018/11/22 Javascript
zepto.js 实时监听输入框的方法
2018/12/04 Javascript
Jquery ajax书写方法代码实例解析
2020/06/12 jQuery
[01:09]2014DOTA2国际邀请赛 TI4西雅图DOTA2 中国美女coser加油助威
2014/07/20 DOTA
[07:09]2014DOTA2国际邀请赛-Newbee再次发威成功晋级决赛
2014/07/19 DOTA
python处理PHP数组文本文件实例
2014/09/18 Python
Python类定义和类继承详解
2015/05/08 Python
Python中pow()和math.pow()函数用法示例
2018/02/11 Python
Python中的函数式编程:不可变的数据结构
2018/10/08 Python
Python多线程获取返回值代码实例
2020/02/17 Python
Python接口测试结果集实现封装比较
2020/05/01 Python
matplotlib部件之矩形选区(RectangleSelector)的实现
2021/02/01 Python
HTML5 语音搜索只需一句代码
2013/01/03 HTML / CSS
英国折扣零售连锁店:QD Stores
2018/12/08 全球购物
Myprotein比利时官方网站:欧洲第一运动营养品牌
2020/10/04 全球购物
银行实习人员自我鉴定
2013/09/22 职场文书
优秀通讯员事迹材料
2014/01/28 职场文书
留学生求职信
2014/06/03 职场文书
集中采购方案
2014/06/10 职场文书
我的梦想演讲稿500字
2014/08/21 职场文书
基于Redis延迟队列的实现代码
2021/05/13 Redis
table设置超出部分隐藏,鼠标移上去显示全部内容的方法
2022/12/24 HTML / CSS