PHP、Python和Javascript的装饰器模式对比

 更新时间:2015年02月03日 09:08:39   作者:Hito''s Blog  
这篇文章主要介绍了PHP、Python和Javascript的装饰器模式对比,修饰模式(Decorator Pattern),又叫装饰者模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式,需要的朋友可以参考下

修饰模式(Decorator Pattern),又叫装饰者模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。装饰模式非常适用于灵活扩展对象的功能,下面是装饰模式的UML图:

例如,有一个技术论坛,用户通过留言进行沟通,由于刚开始论坛里都是熟人,几乎都不需要对留言的内容作出审核,接收留言的页面可以是这样:

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中try{}catch{}的使用方法

    浅谈PHP中try{}catch{}的使用方法

    下面小编就为大家带来一篇浅谈PHP中try{}catch{}的使用方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • ThinkPHP查询返回简单字段数组的方法

    ThinkPHP查询返回简单字段数组的方法

    这篇文章主要介绍了ThinkPHP查询返回简单字段数组的方法,是ThinkPHP查询功能中一个非常实用的技巧,需要的朋友可以参考下
    2014-08-08
  • Laravel 自动转换长整型雪花 ID 为字符串的实现

    Laravel 自动转换长整型雪花 ID 为字符串的实现

    这篇文章主要介绍了Laravel 自动转换长整型雪花 ID 为字符串的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • php筛选不存在的图片资源

    php筛选不存在的图片资源

    本文给大家汇总了几个使用php实现筛选不存在图片资源的方法,非常的简单实用,有需要的小伙伴可以参考下。
    2015-04-04
  • C/S和B/S两种架构区别与优缺点分析

    C/S和B/S两种架构区别与优缺点分析

    C/S和B/S,是再普通不过的两种软件架构方式,都可以进行同样的业务处理,甚至也可以用相同的方式实现共同的逻辑。既然如此,为何还要区分彼此呢?那我们就来看看二者的区别和联系。
    2014-10-10
  • 仿Aspnetpager的一个PHP分页类代码 附源码下载

    仿Aspnetpager的一个PHP分页类代码 附源码下载

    最近正在学习php,想拿一些demo来练习一下,想起前段时间自己用.net写的仿Aspnetpager控件的分页类,就琢磨着用PHP来实现仿aspnetpager的分页功能,随便复习下
    2012-10-10
  • php reset() 函数指针指向数组中的第一个元素并输出实例代码

    php reset() 函数指针指向数组中的第一个元素并输出实例代码

    在php中,当我们使用next函数或end函数将数组内部针指指向数组最后一个元素的时候,如果再需要将内部指针指向第一个元素,可以使用reset() 函数来实现,本文章向大家讲解reset() 函数的基本语法及使用实例,需要的朋友可以参考下
    2016-11-11
  • Thinkphp5框架ajax接口实现方法分析

    Thinkphp5框架ajax接口实现方法分析

    这篇文章主要介绍了Thinkphp5框架ajax接口实现方法,结合实例形式分析了thinkPHP5 ajax交互相关操作技巧,需要的朋友可以参考下
    2019-08-08
  • PHP中的Trait 特性及作用

    PHP中的Trait 特性及作用

    Traits 是一种为类似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用方法集
    2016-04-04
  • 清除laravel缓存命令代码实例

    清除laravel缓存命令代码实例

    这篇文章主要介绍了清除laravel缓存命令代码实例,这个是在应用终端中直接命令清除,有感兴趣的同学可以学习下
    2021-03-03

最新评论