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下删除一篇文章生成的多个静态页面
Aug 08 PHP
.htaccess文件保护实例讲解
Feb 06 PHP
Mysql的Root密码忘记,查看或修改的解决方法(图文介绍)
Jun 14 PHP
解析php中static,const与define的使用区别
Jun 18 PHP
浅析php中如何在有限的内存中读取大文件
Jul 02 PHP
php获取文件大小的方法
Feb 26 PHP
CentOS 6.3下安装PHP xcache扩展模块笔记
Sep 10 PHP
php中get_meta_tags()、CURL与user-agent用法分析
Dec 16 PHP
yii的入口文件index.php中为什么会有这两句
Aug 04 PHP
PHP laravel中的多对多关系实例详解
Jun 07 PHP
php传值和传引用的区别点总结
Nov 19 PHP
php中yii框架实例用法
Dec 22 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函数
2010/02/16 PHP
php简单对象与数组的转换函数代码(php多层数组和对象的转换)
2011/05/18 PHP
探讨Hessian在PHP中的使用分析
2013/06/13 PHP
如何让搜索引擎抓取AJAX内容解决方案
2014/08/25 PHP
php将数组存储为文本文件方法汇总
2015/10/28 PHP
PHP实现原生态图片上传封装类方法
2016/11/08 PHP
strpos() 函数判断字符串中是否包含某字符串的方法
2019/01/16 PHP
使用隐藏的new来创建对象
2011/03/29 Javascript
Js实现动态添加删除Table行示例
2014/04/14 Javascript
js简单倒计时实现代码
2016/04/30 Javascript
Android中Okhttp3实现上传多张图片同时传递参数
2017/02/18 Javascript
js学习总结_轮播图之渐隐渐现版(实例讲解)
2017/07/17 Javascript
Vue自定义指令实现checkbox全选功能的方法
2018/02/28 Javascript
Nodejs异步回调之异常处理实例分析
2018/06/22 NodeJs
通过javascript实现段落的收缩与展开
2019/06/26 Javascript
JS实现横向跑马灯效果代码
2020/04/20 Javascript
js 获取扫码枪输入数据的方法
2020/06/10 Javascript
学习 Vue.js 遇到的那些坑
2021/02/02 Vue.js
python的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享
2014/07/09 Python
Python统计日志中每个IP出现次数的方法
2015/07/06 Python
python实现文本文件合并
2015/12/29 Python
python 3利用BeautifulSoup抓取div标签的方法示例
2017/05/28 Python
获取django框架orm query执行的sql语句实现方法分析
2019/06/20 Python
python将时分秒转换成秒的实例
2019/12/07 Python
浅谈Python中threading join和setDaemon用法及区别说明
2020/05/02 Python
美国时尚孕妇装品牌:A Pea in the Pod
2017/07/16 全球购物
最耐用行李箱,一箱永流传:Briggs & Riley(全球终身保修)
2017/12/07 全球购物
运动会800米加油稿
2014/02/22 职场文书
大学毕业生求职自荐书
2014/06/05 职场文书
大学生职业生涯规划大赛作品(精品)
2014/09/17 职场文书
公民授权委托书
2014/10/15 职场文书
租车协议书范本2014
2014/11/17 职场文书
超市员工管理制度
2015/08/06 职场文书
Django实现聊天机器人
2021/05/31 Python
nginx配置之并发频次限制
2022/04/18 Servers
Mysql 文件配置解析介绍
2022/05/06 MySQL