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 相关文章推荐
NOD32 v2.70.32 简体中文封装版 提供下载了
Feb 27 PHP
PHP字符串 ==比较运算符的副作用
Oct 21 PHP
PHP Socket 编程
Apr 09 PHP
深入密码加salt原理的分析
Jun 06 PHP
PHP防止跨域提交表单
Nov 01 PHP
php绘图中显示不出图片的原因及解决
Mar 05 PHP
PHP正则表达式替换站点关键字链接后空白的解决方法
Sep 16 PHP
使用xampp搭建运行php虚拟主机的详细步骤
Oct 21 PHP
php基于自定义函数记录log日志方法
Jul 21 PHP
PHP中的empty、isset、isnull的区别与使用实例
Mar 22 PHP
PHP远程连接oracle数据库操作实现方法图文详解
Apr 11 PHP
apache集成php7.3.5的详细步骤
Jun 20 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 变量类型的强制转换
2009/10/23 PHP
php图片加水印原理(超简单的实例代码)
2013/01/18 PHP
PHP正则替换函数preg_replace和preg_replace_callback使用总结
2014/09/22 PHP
在win7中搭建Linux+PHP 开发环境
2014/10/08 PHP
PHP实现将MySQL重复ID二维数组重组为三维数组的方法
2016/08/01 PHP
PHP使用SMTP邮件服务器发送邮件示例
2018/08/28 PHP
laravel 使用事件系统统计浏览量的实现
2019/10/16 PHP
JavaScript内核之基本概念
2011/10/21 Javascript
json数据的列循环示例
2013/09/06 Javascript
JavaScript instanceof 的使用方法示例介绍
2013/10/23 Javascript
Javascript核心读书有感之表达式和运算符
2015/02/11 Javascript
把多个JavaScript函数绑定到onload事件处理函数上的方法
2016/09/04 Javascript
js控制一个按钮是否可点击(可使用)disabled的实例
2017/02/14 Javascript
详解React-Native全球化多语言切换工具库react-native-i18n
2017/11/03 Javascript
动态Axios的配置步骤详解
2018/01/12 Javascript
vue+web端仿微信网页版聊天室功能
2019/04/30 Javascript
vue如何获取自定义元素属性参数值的方法
2019/05/14 Javascript
Vue.js实现tab切换效果
2019/07/24 Javascript
5分钟快速看懂ES6中的反射与代理
2019/12/19 Javascript
JavaScript中this的学习笔记及用法整理
2020/02/17 Javascript
[02:14]2016国际邀请赛中国区预选赛Ehome晋级之路
2016/07/01 DOTA
[01:02:00]DOTA2-DPC中国联赛 正赛 Elephant vs IG BO3 第三场 1月24日
2021/03/11 DOTA
Python利用正则表达式匹配并截取指定子串及去重的方法
2015/07/30 Python
不要用强制方法杀掉python线程
2017/02/26 Python
Python语言描述机器学习之Logistic回归算法
2017/12/21 Python
python导入坐标点的具体操作
2019/05/10 Python
Python并发concurrent.futures和asyncio实例
2020/05/04 Python
python简单实现9宫格图片实例
2020/09/03 Python
python网络爬虫实现发送短信验证码的方法
2021/02/25 Python
巴西服装和鞋子购物网站:Marisa
2018/10/25 全球购物
Chinti & Parker官网:奢华羊绒女装和创新针织设计
2021/01/01 全球购物
大学生毕业求职的自我评价
2013/09/29 职场文书
商务日语专业自荐信
2014/04/17 职场文书
幼儿园师德演讲稿
2014/05/06 职场文书
入党后的感想
2015/08/10 职场文书
少儿励志名言(80句)
2019/08/14 职场文书