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的知识
Nov 17 PHP
自动把纯文本转换成Web页面的php代码
Aug 27 PHP
destoon复制新模块的方法
Jun 21 PHP
php中header跳转使用include包含解决参数丢失问题
May 08 PHP
PHP简单实现HTTP和HTTPS跨域共享session解决办法
May 27 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
Dec 10 PHP
Yii2框架dropDownList下拉菜单用法实例分析
Jul 18 PHP
php+Memcached实现简单留言板功能示例
Feb 15 PHP
ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解
Apr 02 PHP
Laravel框架Request、Response及Session操作示例
May 06 PHP
浅谈laravel中的关联查询with的问题
Oct 10 PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
Feb 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编程开发“虚拟域名”系统
2006/10/09 PHP
PHP新手入门学习方法
2011/05/08 PHP
ThinkPHP之R方法实例详解
2014/06/20 PHP
PHP实现的汉字拼音转换和公历农历转换类及使用示例
2014/07/01 PHP
使用PHP和HTML5 FormData实现无刷新文件上传教程
2014/09/06 PHP
laravel 解决paginate查询多个字段报错的问题
2019/10/22 PHP
Ucren Virtual Desktop V2.0
2006/11/07 Javascript
js 替换功能函数,用正则表达式解决,js的全部替换
2010/12/08 Javascript
js创建数据共享接口——简化框架之间相互传值
2011/10/23 Javascript
jQuery.extend 函数详解
2012/02/03 Javascript
jQuery 无刷新分页实例代码
2013/11/12 Javascript
jquery.ajax的url中传递中文乱码问题的解决方法
2014/02/07 Javascript
推荐6款基于jQuery实现图片效果插件
2014/12/07 Javascript
js改变Iframe中Src的方法
2015/05/05 Javascript
bootstrap布局中input输入框右侧图标点击功能
2016/05/16 Javascript
Javascript 两种刷新方法以及区别和适用范围
2017/01/17 Javascript
Angular组件化管理实现方法分析
2017/03/17 Javascript
原生js实现密码输入框值的显示隐藏
2017/07/17 Javascript
vue如何使用 Slot 分发内容实例详解
2017/09/05 Javascript
node.js中http模块和url模块的简单介绍
2017/10/06 Javascript
Angular使用cli生成自定义文件、组件的方法
2018/09/04 Javascript
详解Vue2.0组件的继承与扩展
2018/11/23 Javascript
小程序实现人脸识别功能(百度ai)
2018/12/23 Javascript
Vue数字输入框组件的使用方法
2019/10/19 Javascript
vue-cli创建的项目中的gitHooks原理解析
2020/02/14 Javascript
浅谈JavaScript中等号、双等号、 三等号的区别
2020/08/06 Javascript
[01:07:19]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第一场
2018/04/06 DOTA
Python时间获取及转换知识汇总
2017/01/11 Python
详解Python中的测试工具
2019/06/09 Python
学习Python列表的基础知识汇总
2020/03/10 Python
解决PyCharm IDE环境下,执行unittest不生成测试报告的问题
2020/09/03 Python
英国折扣零售连锁店:QD Stores
2018/12/08 全球购物
美国第一大药店连锁机构:Walgreens(沃尔格林)
2019/10/10 全球购物
内蒙古鄂尔多斯市市长寄语
2014/04/10 职场文书
廉洁校园实施方案
2014/05/25 职场文书
公务员年终个人总结
2015/02/12 职场文书