七. PHP模式設計執行及描述任務

來源:互聯網
上載者:User
1. 解析器模式//解析器內容類別//用於存放運算式的運算結果,並且能根據傳入的運算式返回當初記錄的結果class InterpreterContext{    private $expressionstore=array();    //將對象放進array裡面,索引號是對象ID號    function replace(Expression $exp,$value){        $this->expressionstore[$exp->getKey()]=$value;    }    function lookup(Expression $exp){        return $this->expressionstore[$exp->getKey()];    }}abstract class Expression{    private static $keyCount=0;    private $key;    abstract function interpret(InterpreterContext $context);    //每一個對象都有一個唯一的key    function getKey(){        if(!isset($this->key)){            $this->key=++self::$keyCount;        }        return $this->key;    }}//字串class LiteralExpression extends Expression{    private $value;    function __construct($value){        $this->value=$value;    }    function interpret(InterpreterContext $context){        $context->replace($this, $this->value);    }}//變數class VariableExpression extends Expression{    private $value;    private $name;    function __construct($name,$value=null){        $this->name=$name;        $this->value=$value;    }    function setValue($value){        $this->value=$value;    }    function getKey(){        return $this->name;    }    function interpret(InterpreterContext $context){        if(!is_null($this->value)){            $context->replace($this, $this->value);            //設定為空白,可以避免在沒有修改value的情況下再次調用該方法的時候,            //也第二次調用了InterpreterContext::replece            $this->value=null;        }    }}//操作符運算式 抽象基類abstract class OperatorExpression extends Expression{    //左右運算元    protected $l_op;    protected $r_op;    function __construct(Expression $l_op,Expression $r_op){        $this->l_op=$l_op;        $this->r_op=$r_op;    }    function interpret(InterpreterContext $context){        $this->l_op->interpret($context);        $this->r_op->interpret($context);        $result_l=$context->lookup($this->l_op);        $result_r=$context->lookup($this->r_op);        $this->doInterpret($context, $result_l, $result_r);    }    protected abstract function doInterpret(InterpreterContext $context,$result_l,$result_r);}//相等運算式class EqualsExpression extends OperatorExpression{    //計算後將結果儲存進this裡...    protected function doInterpret(InterpreterContext $context,$result_l,$result_r){        $context->replace($this, $result_l==$result_r);    }}//布爾或運算式class BooleanOrExpression extends OperatorExpression{    protected function doInterpret(InterpreterContext $context, $result_l, $result_r){        $context->replace($this, $result_l || $result_r);    }}//布爾與運算式class BooleanAndExpression extends OperatorExpression{    protected function doInterpret(InterpreterContext $context, $result_l, $result_r){        $context->replace($this, $result_l && $result_r);    }}/*$context=new InterpreterContext();$literal=new LiteralExpression("Bob");$literal->interpret($context);print $context->lookup($literal);//Bob$context=new InterpreterContext();$myvar=new VariableExpression("V","one");$myvar->interpret($context);print $context->lookup($myvar);//one$myothervar=new VariableExpression("V");$myvar->interpret($context);print $context->lookup($myvar);//one*///利用上面的代碼來檢測迷你型語言//$input equals "4" or $input equals "four"$context=new InterpreterContext();//一個沒有賦值的變數$input=new VariableExpression('input');//定義一個複雜的布爾型變數,初始化的參數被儲存在l_op,r_op裡面//注意,此時他們還沒有進行相關運算,必須等到調用布爾型變數的interpret()//之後,布爾型變數裡面的參數才會各自調用自身的interpret,形成一個調用棧...$statement=new BooleanOrExpression(        new EqualsExpression($input, new LiteralExpression('four')),         new EqualsExpression($input, new LiteralExpression('4')));$statement->interpret($context);print $context->lookup($statement);foreach (array('four','4','52') as $val){    $input->setValue($val);    print "$val:\n";    $statement->interpret($context);    if($context->lookup($statement)){        print "top marks\n";    }else{        print "dunce hat on\n\n";    }}/*four:top marks4:top marks52:dunce hat on*/  2.策略模式      將類中許多不同操作而且是來自同一個介面的演算法,獨立起來封裝在一個新類中,主類在由分類組合或者彙總而成//Question類將由Marker彙總而成abstract class Question{    protected $prompt;    protected $marker;    function __construct($prompt,Marker $marker){        $this->marker=$marker;        $this->prompt=$prompt;    }    //利用委託實現    function mark($response){        return $this->marker->mark($response);    }}class TextQuestion extends Question{    //處理文本問題特有的操作}class AVQuestion extends Question{    //處理語音問題特有操作}//策略對象//將演算法部分獨立出來封裝在Marker類中....abstract class Marker{    protected $test;    function __construct($test){        $this->test=$test;    }    abstract function mark($response);}//MarkLogic語言class MarkLogicMarker extends Marker{    protected $engine;    function __construct($test){        parent::__construct($test);    }    function mark($response){        //類比返回true        return true;    }}//直接匹配class MatchMarker extends Marker{    function mark($response){        return ($this->test==$response);    }}//Regexclass RegexpMarker extends Marker{    function mark($response){        return (preg_match($this->test, $response));    }}//用戶端範例程式碼$markers=array(new RegexpMarker("/f.ve/"),        new MatchMarker("fivev"),        new MarkLogicMarker('$input equals "five"'));foreach($markers as $marker){    print get_class($marker)."\n";    //建立一個問題,將marker執行個體傳進去    $question=new TextQuestion("How many beans make five", $marker);    foreach (array("five","four") as $response){        print "\t response:$response: ";        if($question->mark($response)){            print "well done\n";        }else{            print "never mind\n";        }    }}/*RegexpMarker     response:five: well done     response:four: never mindMatchMarker     response:five: never mind     response:four: never mindMarkLogicMarker     response:five: well done     response:four: well done*/3 觀察者模式     觀察者模式的和興是把客戶元素(觀察者)從一個中心類中分離開來.當主體中有事件發生時,觀察者必須被通知到!同時觀察者和主體類不是通過寫入程式碼實現,而是通過介面組合彙總實現*問題// Login類(主體類)class Login {    const LOGIN_USER_UNKNOWN = 1;    const LOGIN_WRONG_PASS = 2;    const LOGIN_ACCESS = 3;    private $status = array ();    // 登入操    function handleLogin($user, $pass, $ip) {        $ret=false;        switch (rand ( 1, 3 )) {            case 1 :                $this->setStatus ( self::LOGIN_ACCESS, $user, $ip );                $ret=ture;                break;            case 2 :                $this->setStatus ( self::LOGIN_WRONG_PASS, $user, $ip );                $ret=false;                break;            case 3 :                $this->setStatus ( self::LOGIN_USER_UNKNOWN, $user, $ip );                $ret=false;                break;            default:                $ret=false;        }        //如果需要記錄IP時        Logger::logIP($user, $ip, $this->getStatus());        //如果需要把登入失敗的人的IP發送到管理員郵箱時...        if(!$ret){            Notifier::mailWarning($user, $ip, $this->getStatus());        }        //還需要其他功能時,比如特殊IP需要設定cookie等...        //需要在這裡面一直添加...        return $ret;    }    function setStatus($status, $user, $ip) {        $this->status = array ($status,$user,$ip);    }    function getStatus(){        return $this->status;    }}class Logger{    static function logIP($user,$ip,$status){}}class Notifier{    static function mailWarning($user,$ip,$status){}}*利用觀察者模式,使代碼改動少些....// 主體類的抽象介面interface Observable{    //附加    function attach(Observer $observer);    //刪除    function detach(Observer $observer);    //通知    function notify();}// Login類(主體類)class Login implements Observable{    const LOGIN_USER_UNKNOWN = 1;    const LOGIN_WRONG_PASS = 2;    const LOGIN_ACCESS = 3;    private $observers;    private $status = array ();    // 登入操作    function handleLogin($user, $pass, $ip) {        $ret=false;        switch (rand ( 1, 3 )) {            case 1 :                $this->setStatus ( self::LOGIN_ACCESS, $user, $ip );                $ret=ture;                break;            case 2 :                $this->setStatus ( self::LOGIN_WRONG_PASS, $user, $ip );                $ret=false;                break;            case 3 :                $this->setStatus ( self::LOGIN_USER_UNKNOWN, $user, $ip );                $ret=false;                break;            default:                $ret=false;        }        //使用觀察者模式之後,如果需要增加新功能,只需要在本類中添加觀察者執行個體即可...        $this->notify();        return $ret;    }    function setStatus($status, $user, $ip) {        $this->status = array ($status,$user,$ip);    }    function getStatus(){        return $this->status;    }    function attach(Observer $observer){        $this->observers[]=$observer;    }    function detach(Observer $observer){        $newObserver=array();        foreach ($this->observers as $obs){            if($obs!==$observer){                $newObserver[]=$obs;            }        }        $this->observers=$newObserver;    }    //通知所有觀察者    function notify(){        foreach ($this->observers as $bos){            $bos->update($this);        }    }}//觀察者介面interface Observer{    function update(Observable $observable);}class SecurityMonitor implements Observer{    function update(Observable $observable){        //getStatus()不是Observable介面規定的方法        $status=$observable->getStatus();        //對status的判斷也涉及到耦合問題        if($status[0]==Login::LOGIN_WRONG_PASS){            //發送郵件給管理員            print __CLASS__.":\t sending mail to sysadmin\n";        }    }}$login=new Login();$login->attach(new SecurityMonitor());$login->handleLogin("coco", "123456", "127.0.0.1");//有可能輸出發送訊息到管理員 *改進後的觀察者模式//可觀察元素:主體類的基底介面interface Observable{    //附加    function attach(Observer $observer);    //刪除    function detach(Observer $observer);    //通知    function notify();}// Login類(主體類)class Login implements Observable{    const LOGIN_USER_UNKNOWN = 1;    const LOGIN_WRONG_PASS = 2;    const LOGIN_ACCESS = 3;    private $observers;    private $status = array ();    // 登入操作    function handleLogin($user, $pass, $ip) {        $ret=false;        switch (rand ( 1, 3 )) {            case 1 :                $this->setStatus ( self::LOGIN_ACCESS, $user, $ip );                $ret=ture;                break;            case 2 :                $this->setStatus ( self::LOGIN_WRONG_PASS, $user, $ip );                $ret=false;                break;            case 3 :                $this->setStatus ( self::LOGIN_USER_UNKNOWN, $user, $ip );                $ret=false;                break;            default:                $ret=false;        }        //使用觀察者模式之後,如果需要增加新功能,只需要在本類中添加觀察者執行個體即可...        $this->notify();        return $ret;    }    function setStatus($status, $user, $ip) {        $this->status = array ($status,$user,$ip);    }    function getStatus(){        return $this->status;    }    function attach(Observer $observer){        $this->observers[]=$observer;    }    function detach(Observer $observer){        $newObserver=array();        foreach ($this->observers as $obs){            if($obs!==$observer){                $newObserver[]=$obs;            }        }        $this->observers=$newObserver;    }    //通知所有觀察者    function notify(){        foreach ($this->observers as $bos){            $bos->update($this);        }    }}//觀察者介面interface Observer{    function update(Observable $observable);}//Login:觀察者超類(用於解決直接在Observer中調用具體的Observable子類造成的風險)abstract class LoginObserver implements Observer{    private $login;    function __construct(Login $login){        $this->login=$login;        $this->login->attach($this);    }    //該方法在Observable的子類某些方法被調用時觸發    function update(Observable $observable){        //觸發該方法時,傳入的參數必須是Login才有效...        if($this->login===$observable){             $this->doUpdate($observable);        }    }    abstract function doUpdate(Login $login);    }//改進後的觀察者能保證調用的Observable執行個體方法一定存在class SecurityMonitor extends LoginObserver{    function doUpdate(Login $login){        $status=$login->getStatus();        //對status的判斷也涉及到耦合問題        if($status[0]==Login::LOGIN_WRONG_PASS){            //發送郵件給管理員            print __CLASS__.":\t sending mail to sysadmin\n";        }    }}//日常記錄class GeneralLogger extends LoginObserver{    function doUpdate(Login $login){        $status=$login->getStatus();        //添加記錄到log中        //...        print __CLASS__."\t add login data to log\n";    }}//夥伴工具類class PartnershipTool extends LoginObserver{    function doUpdate(Login $login){        $status=$login->getStatus();        //檢查IP,如果匹配,則設定cookie...        //...        print __CLASS__."\t set cookie if IP matches a list\n";    }}//用戶端代碼有一點點改變...$login=new Login();new SecurityMonitor($login);new GeneralLogger($login);new PartnershipTool($login);$login->handleLogin("coco", "123456", "127.0.0.1");/* * 有可能輸出 *SecurityMonitor:     sending mail to sysadmin *GeneralLogger     add login data to log *PartnershipTool    set cookie if IP matches a list **/4. 訪問者模式       當使用對象集合時,我們可能需要對結構上每一個單獨的組件應用各種操作.這樣的操作可以內建於組件本身,畢竟組件內部調用其他組件是最方便的.        但是這種方法也存在問題,因為我們並不知道所有可能需要的執行的操作.如果每增加一個操作,就在類中增加一個對於新操作的支援,類就會變得越來越臃腫.訪問者模式可以解決這個問題.//本例是基於"文明"遊戲的代碼建立而成...//*戰鬥單元類abstract class Unit{    //深度    protected $depth=0;    //攻擊強度    abstract function bombardStrength();    function getComposite(){        return null;    }    //為訪問者模式打造的方法    function accept(ArmyVisitor $visitor){        //構建一個根據自己規則定義的方法名,然後交給visitor自身調用        $method="visit".get_class($this);        $visitor->$method($this);    }    //用於計算Unit在對象樹中的深度    protected function setDepth($depth){        $this->depth==$depth;    }    function getDepth(){        return $this->depth;    }}//複合抽象類別abstract class CompositeUnit extends Unit{    protected $units=array();    //為訪問者模式打造的方法    function accept(ArmyVisitor $visitor){        //構建一個根據自己規則定義的方法名,然後交給visitor自身調用        //先調用父類accept(),再遍曆調用子項目accept()        parent::accept($visitor);        foreach ($this->units as $thisunit){            $thisunit->accept($visitor);        }    }    //可以不用寫bombardStrength()    function getComposite(){        return $this;    }    //添加單元    //同時標記節點在對象樹中的深度    function addUnit(Unit $unit){        if(!empty($unit)){            if(in_array($unit, $this->units,true)){                return;            }            //可以用下面代碼替換in_array()函數//             foreach ($this->units as $thisunit){//                 if($thisunit===$unit){//                     return;//                 }//             }            //計算好深度先...            $unit->setDepth($this->depth+1);            array_push($this->units, $unit);        }    }    function removeUnit(Unit $unit){        $this->units=array_udiff($this->units, array($unit), function ($a,$b){return ($a===$b?0:1);});    }    }//射手class Archer extends Unit{    function bombardStrength(){        return 4;    }}//雷射塔class LaserCannonUnit extends Unit{    function bombardStrength(){        return 44;    }}//軍隊:由戰鬥單元組成class Army extends CompositeUnit{    //計算總強度    function bombardStrength(){        $ret=0;        foreach ($this->units as $unit){            $ret+=$unit->bombardStrength();        }        return $ret;    }    //移動能力,防禦能力...省略}//運兵船:一個類似軍隊的單元,它具備10個戰鬥單元,有攻擊力class TroopCarrier extends CompositeUnit{    //具備和軍隊差不多的方法和屬性    function bombardStrength(){        //Do something...    }}//軍隊訪問者基類abstract class ArmyVisitor{    //相關方法待會寫...    //Army可能有多少種Unit,這裡就有多少個visit方法...    //方法命名規則為visit+類名    //預設的visit    abstract function visit(Unit $unit);    function visitArcher(Archer $node){        $this->visit($node);    }    function visitLaserCannonUnit(LaserCannonUnit $node){        $this->visit($node);    }    function visitArmy(Army $node){        $this->visit($node);    }    function visitTroopCarrier(TroopCarrier $node){        $this->visit($node);    }}//具體的Army訪問者類,用於轉存文本class TextDumpArmyVisitor extends ArmyVisitor{    private $text="";    function visit(Unit $node){        $ret="";        $pad=4*$node->getDepth();        $ret.=sprintf("%{$pad}s","");        $ret.=get_class($node).":";        $ret.="bombard: ".$node->bombardStrength()."\n";        $this->text.=$ret;    }    function getText(){        return $this->text;    }}//用戶端執行個體代碼$army=new Army();$army->addUnit(new Archer());$army->addUnit(new LaserCannonUnit());$textdump=new TextDumpArmyVisitor();$army->accept($textdump);print $textdump->getText();/*   *  Army:bombard: 48 *  Archer:bombard: 4 *  LaserCannonUnit:bombard: 44 */5. 命令模式//命令模式//命令模式最初來源於圖形化使用者介面設計,但現在廣泛應用於公司專屬應用程式設計,特別促進了控制器(請求和分法處理)//和領域模型(應用邏輯)的分離.說得更簡單一點,命令模式有助於系統更好地進行組織,並易於擴充//Command可以設計成介面,因為它很簡單...//Commands/Command.phpabstract class Command{    abstract function execute(CommandContext $context);}  require_once("Command.php");class Registry{    //一個空類...    static function getAccessManager(){        return new AccessManager();    }}class AccessManager{    function login(){        return new stdClass();    }    function getError(){}}class LoginCommand extends Command{    function execute(CommandContext $context){        $manager=Registry::getAccessManager();        $user=$context->get('username');        $user=$context->get('pass');        //虛構出來的空類空方法        $user_obj=$manager->login();        if(is_null($user_obj)){            $context->setError($manager->getError());            return false;        }        $context->addParam("user", $user);        return true;    }}  //CommandContext類用來做任務擴增用,在這兒主要功能是傳遞資料給Command類class CommandContext{    private $params=array();    private $error="";    function __construct(){        $this->params=$_REQUEST;    }    function addParam($key,$val){        $this->params[$key]=$val;    }    function get($key){        return $this->params[$key];    }    function setError($error){        $this->error=$error;    }    function getError(){        return $this->error;    }}//用戶端代碼(用於建立命令)已經調用者代碼class CommandNotFoundException extends Exception{    }//建立命令的工廠class CommandFactory{    private static $dir="Commands";    //根據參數action,以及類檔案存放目錄$dir動態建立相應的$action+Command類    static function getCommand($action='default'){        //匹配是否出現非法字元(非字母數字底線)        if(preg_match('/\W/', $action)){            throw new Exception("Illegal characters in action");        }        $class=ucfirst(strtolower($action)."Command");        $file=self::$dir.DIRECTORY_SEPARATOR."{$class}.php";        if(!file_exists($file)){            throw new CommandNotFoundException("File could not be find !");        }        require_once("$file");        if(!class_exists($class)){            throw new CommandNotFoundException("Class could not be find !");        }        return new $class();    }}//調用者,裡麵包含一個CommandContext對象執行個體,用於存放web請求的資料class Controller{    private $context;    function __construct(){        $this->context=new CommandContext();    }    function getContext(){        return $this->context;    }    function process(){        $cmd=CommandFactory::getCommand($this->getContext()->get('action'));        if(!$cmd->execute($this->context)){            //處理失敗            print "Faile in process!";        }else{            //處理成功,可以顯示相應的視圖層            print "Success in process!";        }    }}$controller=new Controller();$context=$controller->getContext();$context->addParam('action', 'Login');$context->addParam('user', 'cocos');$context->addParam('pass', 'tiddles');//controller執行process方法,需要不理解command的意義.$controller->process();//Success in process
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.