您好,欢迎访问一九零五行业门户网

七. PHP模式设计----执行及描述任务_PHP教程

七. php模式设计----执行及描述任务 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); }}//正则表达式class 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
http://www.bkjia.com/phpjc/914777.htmlwww.bkjia.comtruehttp://www.bkjia.com/phpjc/914777.htmltecharticle七. php模式设计----执行及描述任务 1. 解析器模式//解析器内容类//用于存放表达式的运算结果,并且能根据传入的表达式返回当初记录的结果...
其它类似信息

推荐信息