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 相关文章推荐
BBS(php & mysql)完整版(八)
Oct 09 PHP
一段防盗连的PHP代码
Dec 06 PHP
PHP has encountered an Access Violation 错误的解决方法
Jan 17 PHP
PHP 开发环境配置(测试开发环境)
Apr 28 PHP
php中通过curl检测页面是否被百度收录
Sep 27 PHP
11个PHPer必须要了解的编程规范
Sep 22 PHP
php实现的发送带附件邮件类实例
Sep 22 PHP
memcache一致性hash的php实现方法
Mar 05 PHP
PHP检测用户语言的方法
Jun 15 PHP
php下载文件,添加响应头的简单实例
Sep 22 PHP
PHP常用算法和数据结构示例(必看篇)
Mar 15 PHP
CI框架教程之优化验证码机制详解【验证码辅助函数】
Apr 16 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
漫威DC御用漫画家去世 他的表情包曾走红网络
2020/04/09 欧美动漫
mysql 性能的检查和优化方法
2009/06/21 PHP
Fine Uploader文件上传组件应用介绍
2013/01/06 PHP
php中使用getimagesize获取图片、flash等文件的尺寸信息实例
2014/04/29 PHP
PHP实现生成透明背景的PNG缩略图函数分享
2014/07/08 PHP
php 参数过滤、数据过滤详解
2015/10/26 PHP
详解PHP的Yii框架中扩展的安装与使用
2016/04/01 PHP
php命名空间设计思想、用法与缺点分析
2019/07/17 PHP
php+js实现点赞功能的示例详解
2020/08/07 PHP
javascript 程序库的比较(一)之DOM功能
2010/04/07 Javascript
js操作时间(年-月-日 时-分-秒 星期几)
2010/06/20 Javascript
js利用数组length属性清空和截短数组的小例子
2014/01/15 Javascript
在JS数组特定索引处指定位置插入元素
2014/07/27 Javascript
兼容Firefox的Javascript XSLT 处理XML文件
2014/12/31 Javascript
JSONP之我见
2015/03/24 Javascript
Javascript实现Array和String互转换的方法
2015/12/21 Javascript
JS访问DOM节点方法详解
2016/11/29 Javascript
html5 canvas 详细使用教程
2017/01/20 Javascript
Vuejs 组件——props数据传递的实例代码
2017/03/07 Javascript
详解vue前后台数据交互vue-resource文档
2017/07/19 Javascript
jQuery DOM节点的遍历方法小结
2017/08/15 jQuery
vue.js如何将echarts封装为组件一键使用详解
2017/10/10 Javascript
浅析node Async异步处理模块用例分析及常用方法介绍
2017/11/17 Javascript
webpack之devtool详解
2018/02/10 Javascript
微信小程序表单弹窗实例
2018/07/19 Javascript
Vue实现本地购物车功能
2018/12/05 Javascript
jQuery实现条件搜索查询、实时取值及升降序排序的方法分析
2019/05/04 jQuery
Vue+Node实现商品列表的分页、排序、筛选,添加购物车功能详解
2019/12/07 Javascript
js轮播图之旋转木马效果
2020/10/13 Javascript
[01:12:27]EG vs Secret 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
[07:37]DOTA2-DPC中国联赛2月2日Recap集锦
2021/03/11 DOTA
pytorch 自定义卷积核进行卷积操作方式
2019/12/30 Python
一文读懂Python 枚举
2020/08/25 Python
英国儿童家具专卖店:GLTC
2016/09/24 全球购物
当我正在为表建立索引的时候,SQL Server 会禁止对表的访问吗
2014/04/28 面试题
《梅花魂》教学反思
2014/04/30 职场文书