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 相关文章推荐
第十二节--类的自动加载
Nov 16 PHP
PHP 输出缓存详解
Jun 20 PHP
PHP计划任务之关闭浏览器后仍然继续执行的函数
Jul 22 PHP
PHP通过正则表达式下载图片到本地的实现代码
Sep 19 PHP
PHP数组 为文章加关键字连接 文章内容自动加链接
Dec 29 PHP
ThinkPHP实现一键清除缓存方法
Jun 26 PHP
PHP中设置一个严格30分钟过期Session面试题的4种答案
Jul 30 PHP
PHP环境中Memcache的安装和使用
Nov 05 PHP
php实现等比例不失真缩放上传图片的方法
Nov 14 PHP
PHP实现简单计算器小程序
Aug 28 PHP
PHP simplexml_load_string()函数实例讲解
Feb 03 PHP
YII框架http缓存操作示例
Apr 29 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
一条久听不愿放下的DIY森海MX500,三言两语话神奇
2021/03/02 无线电
PHP生成Flash动画的实现代码
2010/03/12 PHP
php读取EXCEL文件 php excelreader读取excel文件
2012/12/06 PHP
深入理解require与require_once与include以及include_once的区别
2013/06/05 PHP
php后台如何避免用户直接进入方法实例
2013/10/15 PHP
php之curl实现http与https请求的方法
2014/10/21 PHP
php读取XML的常见方法实例总结
2017/04/25 PHP
thinkphp5.1框架容器与依赖注入实例分析
2019/07/23 PHP
在服务端(Page.Write)调用自定义的JS方法详解
2013/08/09 Javascript
PHP PDO操作总结
2014/11/17 Javascript
跟我学习javascript的严格模式
2015/11/16 Javascript
非常棒的jQuery图片轮播效果
2016/04/17 Javascript
Angular.js中用ng-repeat-start实现自定义显示
2016/10/18 Javascript
简单谈谈JS中的正则表达式
2017/09/11 Javascript
webpack学习教程之前端性能优化总结
2017/12/05 Javascript
Thinkjs3新手入门之如何使用静态资源目录
2017/12/06 Javascript
关于微信公众号开发无法支付的问题解决
2018/12/28 Javascript
Layui表格行工具事件与数据回填方法
2019/09/13 Javascript
浅谈JavaScript窗体Window.ShowModalDialog使用
2020/07/22 Javascript
antd Form组件方法getFieldsValue获取自定义组件的值操作
2020/10/29 Javascript
[00:12]DAC2018 Miracle-站上中单舞台,他能否再写奇迹?
2018/04/06 DOTA
Python操作MongoDB详解及实例
2017/05/18 Python
对YOLOv3模型调用时候的python接口详解
2019/08/26 Python
tensorflow对图像进行拼接的例子
2020/02/05 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
2020/04/12 Python
英国网上花店:Bunches
2016/11/29 全球购物
美国最大的骑马用品零售商:HorseLoverZ
2017/01/12 全球购物
马歇尔耳机官网:Marshall Headphones
2020/02/04 全球购物
专业毕业生个性的自我评价
2013/10/03 职场文书
幼儿园春游活动方案
2014/01/19 职场文书
遗嘱公证书标准样本
2014/04/08 职场文书
学校安全管理责任书
2014/07/23 职场文书
mysql事务对效率的影响分析总结
2021/10/24 MySQL
上个世纪50年代的可穿戴技术:无线电帽子
2022/02/18 无线电
Redis 哨兵机制及配置实现
2022/03/25 Redis
解决Springboot PostMapping无法获取数据的问题
2022/05/06 Java/Android