2014年5月

解释器模式,作为PHPer应该非常非常非常熟悉的一种,尽管不知道它叫做解释器模式,但是肯定使用过它。在解释器模式的最佳应用,就是大量优秀的模板引擎。解释器模式解决了一种特定的类型的问题发生的频率足够高,那么就可能值得将该问题的各个势力表述为一个简单的语言中的句子。这就构建了一个解释器,解释器他哦各国解释这些句子来解决问题。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
比如:模板引擎smart;比如论坛的UBB代码,就是用[url=http://www.lanecn.com]LaneBlog[/url]来表示<a href="http://www.lanecn.com/>LaneBlog</a>;还比如正则表达式等
场景:a表示你,b表示好,c表示世界。1表示我说,2表示你说。以PHP为代码环境,模拟设计模式之解释器模式的代码实现。

<?php
class Content{
    private $content = '';
    public function get(){
        return $this->content;
    }
    public function set($content){
        $this->content = $content;
    }
}
class Expression{
    public function interpret($contentObj){
        $content = $contentObj->get();
        if(!empty($content)){
            $lenth = strlen($content);
            for($i=0; $i<$lenth; $i++){
                if(is_numeric($content[$i])){
                    Number::excute($content[$i]);
                }else if(is_string($content[$i])){
                    String::excute($content[$i]);
                }
            }
        }
    }
}
class Number{
    public static function excute($value){
        $data = '';
        switch($value){
            case 1:
                $data = '我说:';
                break;
            case 2:
                $data = '你说:';
                break;
            default:
                break;
        }
        echo $data;
    }
}
//a表示你,b表示好,c表示世界。1表示我说,2表示你说
class String{
    public static function excute($value){
        $data = '';
        switch($value){
            case 'a':
                $data = '你';
                break;
            case 'b':
                $data = '好';
                break;
            case 'c':
                $data = '世界';
                break;
            default:
                break;
        }
        echo $data;
    }
}
//客户端/接口
$contentObj = new Content();
$str = '1abc';
$contentObj->set($str);
echo '解密' . $str . ':<br>';
$expression = new Expression();
$expression->interpret($contentObj);
echo '<br>';
$str = '2abc';
$contentObj->set($str);
echo '解密' . $str . ':<br>';
$expression = new Expression();
$expression->interpret($contentObj);

享元模式解决了大量几乎相似的对象的这种情况。设计模式中的享元模式使程序运行时更加节省服务器资源。享元模式是一种非常好的设计模式。如果一个应用程序使用了大量的对象,而大量的这些对象对服务器资源造成了很大的开销和压力时,就应该考虑使用享元模式。
享元模式:运用共享技术有效的支持大量的细粒度对象。
比如:围棋只有黑白两种棋子,用一个对象生成黑棋子,一个对象生成白棋子,是要一份代码共享给所有的黑棋子共同使用呢,还是每个黑棋子独立一个对象。这就是享元模式,共享对象以达到节省开销的目的。
场景:阿里云旗下的万网提供快速建站的服务,它是给每个用户独立生成一个网站所有的源代码,还是说同类型的网站共享一份代码?答案是后者(示例仅为说明享元模式,并不代表万网的真实实现方式)。以PHP为代码环境,模拟设计模式之享元模式的代码实现。

<?php
class User{
    private $name;
    public function __construct($name){
        $this->setName($name);
    }
    public function setName($name){
        $this->name = $name;
    }
    public function getName(){
        return $this->name;
    }
}
abstract class Website{
    private $name;
    public function __construct($name){
        $this->setName($name);
    }
    public function setName($name){
        $this->name = $name;
    }
    public function getName(){
        return $this->name;
    }
}
class ConcreteWebsite extends Website{
    public function __construct($name){
        parent::__construct($name);
    }
    public function useWebsite($userObj){
        echo '网站名称:' . $this->getName() . '。 所属用户' . $userObj->getName() . '<br>';
    }
}
class WebsiteFactory{
    private $userWebsiteList = array();
    public function getWebsite($key, $name){
        if(!isset($this->userWebsiteList[$key])){
            $this->userWebsiteList[$key] = new ConcreteWebsite($name);
        }
        return $this->userWebsiteList[$key];
    }
}
//客户端/接口
//网站工厂
$websiteFactory = new WebsiteFactory();

//采用万网提供的第一套模板并起名
$website = $websiteFactory->getWebsite('1', 'LaneBlog');
$website->useWebsite(new User('小轩'));

//采用万网提供的第一套模板并起名
$website = $websiteFactory->getWebsite('1', 'Lane博客');
$website->useWebsite(new User('小明'));

//采用万网提供的第一套模板并起名
$website = $websiteFactory->getWebsite('1', 'LixuanBlog');
$website->useWebsite(new User('小红'));

//采用万网提供的第二套模板并起名
$website = $websiteFactory->getWebsite('2', '论坛');
$website->useWebsite(new User('小白'));

根据结果可以看到,多个用户,前三个用户使用的是同一套系统。节省开销。至于名称,从库里读出来即可。这里完全不需要。