PHP、Python和Javascript的裝飾器模式對比
修飾模式(Decorator Pattern),又叫裝飾者模式,是面向?qū)ο缶幊填I(lǐng)域中,一種動態(tài)地往一個類中添加新的行為的設(shè)計模式。就功能而言,修飾模式相比生成子類更為靈活,這樣可以給某個對象而不是整個類添加一些功能。裝飾模式非常適用于靈活擴展對象的功能,下面是裝飾模式的UML圖:

例如,有一個技術(shù)論壇,用戶通過留言進行溝通,由于剛開始論壇里都是熟人,幾乎都不需要對留言的內(nèi)容作出審核,接收留言的頁面可以是這樣:
class SaveMsg(){
private $msg;
public function __construct($msg){
$this->msg=$msg;
}
public function __store(){
//存入數(shù)據(jù)庫
}
}
后來,隨著論壇逐漸出名,就有一些人在上面發(fā)鏈接,就需要對含有鏈接的消息進行過濾,論壇進一步發(fā)展,發(fā)現(xiàn)除開發(fā)垃圾鏈接的外,還有很多無用的灌水,到后來可能還有攻擊等等各種不正常的帖子,所以對論壇帖子的管理,可以單獨抽象出一個類進行管理,當需要擴充過濾規(guī)則時,可以進行動態(tài)擴充。
//基類
abstract class Filter{
abstract public function isForbid();
}
//基礎(chǔ)過濾類
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;
}
}
//新過濾器,判斷是否重復(fù)發(fā)帖
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"){
//判定是否重復(fù)發(fā)帖
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中,不存在抽象類和方法,實現(xiàn)就更加簡單:
#!/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缺少類的特性,繼承對于它來說就顯得有點雞肋了,上面的代碼看起來更像是對兩個函數(shù)的處理, 在python中,有更加簡單的添加裝飾器的方法,直接通過”@”給函數(shù)自動添加裝飾器,達到擴展功能的目的,如:
def Decorator(F):
def newF(age):
print "You Are Calling",F.__name__
F(age)
return newF
@Decorator
#通過@給函數(shù)showAge添加裝飾器Decorator
def showAge(age):
print "hello , i am %d years old"%age
showAge(10)
裝飾模式的目的是解決動態(tài)擴展功能的難題,裝飾模式的本質(zhì)是對對象的靈活處理,理解裝飾模式,不僅能深入了解面向?qū)ο蟮某绦蛟O(shè)計,更能提高編程的思維能力。
相關(guān)文章
實用的PHP帶公鑰加密類分享(每次加密結(jié)果都不一樣哦)
這篇文章主要介紹了實用的PHP帶公鑰加密類分享,本類實現(xiàn)每次的加密結(jié)果都不一樣,但解密沒有問題,非常實用的一個加密類,需要的朋友可以參考下2014-08-08
Laravel實現(xiàn)通過blade模板引擎渲染視圖
今天小編就為大家分享一篇Laravel實現(xiàn)通過blade模板引擎渲染視圖,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10
destoon文章模塊調(diào)用企業(yè)會員資料的方法
這篇文章主要介紹了destoon文章模塊調(diào)用企業(yè)會員資料的方法,非常實用的一個技巧,需要的朋友可以參考下2014-08-08
Yii2學(xué)習筆記之漢化yii設(shè)置表單的描述(屬性標簽attributeLabels)
這篇文章主要介紹了Yii2學(xué)習筆記之漢化yii設(shè)置表單的描述(屬性標簽attributeLabels),非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-02-02

