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发电子邮件
Oct 09 PHP
php下清空字符串中的HTML标签的代码
Sep 06 PHP
php购物车实现代码
Oct 10 PHP
深入分析使用mysql_fetch_object()以对象的形式返回查询结果
Jun 05 PHP
DOM XPATH获取img src值的query
Sep 23 PHP
WordPress中自定义后台管理界面配色方案的小技巧
Dec 29 PHP
PHP实现导出带样式的Excel
Aug 28 PHP
Yii2实现ActiveForm ajax提交
May 26 PHP
PHP实现的登录页面信息提示功能示例
Jul 24 PHP
PHP对象的浅复制与深复制的实例详解
Oct 26 PHP
php时间戳转换代码详解
Aug 04 PHP
Yii 框架使用Forms操作详解
May 18 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/08/08 PHP
PHP批量删除、清除UTF-8文件BOM头的代码实例
2014/04/14 PHP
ThinkPHP内置jsonRPC的缺陷分析
2014/12/18 PHP
PHP读取txt文本文件并分页显示的方法
2015/03/11 PHP
PHP SOCKET编程详解
2015/05/22 PHP
PHP实现的XML操作类【XML Library】
2016/12/29 PHP
php设计模式之装饰模式应用案例详解
2019/06/17 PHP
YUI 读码日记之 YAHOO.util.Dom - Part.1
2008/03/22 Javascript
javascript创建和存储cookie示例
2014/01/07 Javascript
JavaScript实现同时调用多个函数的方法
2015/11/09 Javascript
AngularJS基础 ng-class-odd 指令示例
2016/08/01 Javascript
Angular2从搭建环境到开发步骤详解
2016/10/17 Javascript
Avalonjs 实现简单购物车功能(实例代码)
2017/02/07 Javascript
nodejs个人博客开发第四步 数据模型
2017/04/12 NodeJs
微信小程序 实现列表项滑动显示删除按钮的功能
2017/04/13 Javascript
使用yeoman构建angular应用的方法
2017/08/14 Javascript
JS路由跳转的简单实现代码
2017/09/21 Javascript
Vue Element使用icon图标教程详解(第三方)
2018/02/07 Javascript
深入浅析JS中的严格模式
2018/06/04 Javascript
Vue中通过Vue.extend动态创建实例的方法
2019/08/13 Javascript
Vue通过Blob对象实现导出Excel功能示例代码
2020/07/31 Javascript
js屏蔽F12审查元素,禁止修改页面代码等实现代码
2020/10/02 Javascript
[01:11]回顾历届DOTA2国际邀请赛中国区预选赛
2017/06/26 DOTA
python在windows下实现备份程序实例
2014/07/04 Python
Python内置函数——__import__ 的使用方法
2017/11/24 Python
python如何通过实例方法名字调用方法
2018/03/21 Python
HEMA法国:荷兰原创设计
2019/02/21 全球购物
教师师德教育的自我评价
2013/10/31 职场文书
保安的辞职报告怎么写
2014/01/20 职场文书
《猫》教学反思
2014/02/26 职场文书
大型公益活动策划方案
2014/08/20 职场文书
思想作风整顿个人剖析材料
2014/10/06 职场文书
道士塔读书笔记
2015/06/30 职场文书
2015年中学团委工作总结
2015/07/22 职场文书
HTML+css盒子模型案例(圆,半圆等)“border-radius” 简单易上手
2021/05/10 HTML / CSS
《极主夫道》真人电影正式预告 定档6月3日上映
2022/04/05 日漫