修飾模式(Decorator Pattern),又叫裝飾者模式,是物件導向程式設計領域中,一種動態地往一個類別中加入新的行為的設計模式。就功能而言,修飾模式相比產生子類別更為靈活,這樣可以為某個物件而不是整個類別添加一些功能。
例如,有一個技術論壇,用戶透過留言溝通,由於剛開始論壇裡都是熟人,幾乎都不需要對留言的內容作出審核,接收留言的頁面可以是這樣:
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)
裝飾模式的目的是解決動態擴展功能的難題,裝飾模式的本質是對物件的靈活處理,理解裝飾模式,不僅能深入了解面向物件的程式設計,更能提升程式設計的思考能力。
以上是Javascript的裝飾器模式與php、python對比用法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!