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写的采集程序
Mar 16 PHP
php 面试碰到过的问题 在此做下记录
Jun 09 PHP
ecshop 批量上传(加入自定义属性)
Mar 20 PHP
浅析PHP substr,mb_substr以及mb_strcut的区别和用法
Jun 21 PHP
php与flash as3 socket通信传送文件实现代码
Aug 16 PHP
关于URL最大长度限制的相关资料查证
Dec 23 PHP
PHP Curl模拟登录微信公众平台、新浪微博实例代码
Jan 28 PHP
PHP框架性能测试报告
May 08 PHP
使用PHPExcel导出Excel表
Sep 08 PHP
TP5.0框架实现无限极回复功能的方法分析
May 04 PHP
Centos7安装swoole扩展操作示例
Mar 26 PHP
如何用PHP实现多线程编程
May 26 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程序员基本要求和必备技能
2014/05/09 PHP
PHP将字符分解为多个字符串的方法
2014/11/22 PHP
10个值得深思的PHP面试题
2016/11/14 PHP
解析PHP之提取多维数组指定列的方法
2017/01/03 PHP
jQuery EasyUI API 中文文档 - NumberBox数字框
2011/10/13 Javascript
正负小数点后两位浮点数实现原理及代码
2013/09/06 Javascript
JQuery实现倒计时按钮具体方法
2013/11/14 Javascript
JS实现1000以内被3或5整除的数字之和
2016/02/18 Javascript
微信小程序 数组(增,删,改,查)等操作实例详解
2017/01/05 Javascript
浅谈express 中间件机制及实现原理
2017/08/31 Javascript
vue2.0使用swiper组件实现轮播效果
2017/11/27 Javascript
浅析Node.js非对称加密方法
2018/01/29 Javascript
微信小程序仿RadioGroup改变样式的处理方案
2018/07/13 Javascript
vue基于viewer实现的图片查看器功能
2019/04/12 Javascript
解决layui 三级联动下拉框更新时回显的问题
2019/09/03 Javascript
swiperjs实现导航与tab页的联动
2020/12/13 Javascript
Flask解决跨域的问题示例代码
2018/02/12 Python
Python实现获取前100组勾股数的方法示例
2018/05/04 Python
pandas 空的dataframe 插入列名的示例
2018/10/30 Python
Python中的几种矩阵乘法(小结)
2019/07/10 Python
Python udp网络程序实现发送、接收数据功能示例
2019/12/09 Python
python类中super() 的使用解析
2019/12/19 Python
python实现信号时域统计特征提取代码
2020/02/26 Python
pyqt5数据库使用详细教程(打包解决方案)
2020/03/25 Python
keras 读取多标签图像数据方式
2020/06/12 Python
Python中flatten( ),matrix.A用法说明
2020/07/05 Python
Python获取指定网段正在使用的IP
2020/12/14 Python
canvas像素点操作之视频绿幕抠图
2018/09/11 HTML / CSS
Mytheresa英国官网:拥有160多个奢侈品品牌
2016/10/09 全球购物
台湾百利市购物中心:e-Payless
2017/08/16 全球购物
竞选村长演讲稿
2014/04/28 职场文书
我们的节日国庆活动方案
2014/08/19 职场文书
中小学生学籍证明
2014/10/25 职场文书
求职简历自我评价范文
2015/03/10 职场文书
导游词之蜀山胜景瓦屋山
2019/11/29 职场文书
Spring中bean集合注入的方法详解
2022/07/07 Java/Android