2010-12-21 61 views
2

我想解析幾種文件格式。我想知道是否正確的面向對象「冒險」創建一個空虛的對象。對象自己拒絕它是否正確?

class ParserFactory 
{ 
    private fn; 

    public function ParserFactory(fn) 
    { 
     this->fn = fn; 
    } 
    public function getParser() 
    { 
     a = new FormatAParser(this->fn); 
     if (a->isValid()) 
     { 
      return(a); 
     } 
     b = new FormatBParser(this->fn); 
     // ... and so on... 
    } 
} 

class FormatAParser 
{ 
    /* 
     The object is telling us if is able to continue to work... 
     **CLEAN OR DIRTY DESIGN ?** 
    */ 
    public function isValid() 
    {    
     header = SomeConversionAndReadingStuff(); 
     if (header != "formatA") 
     { 
      return(false) 
     } 
     return(true); 
    } 
    public function parse() 
    { 
     /* 
     Do the parsing, using the conversion stuff done in isValid 
     */ 
    } 
} 

感謝

編輯
我有很好的答案。所以,對象檢查自己的有效性是可以的。無論如何,我的代碼是un-OOP,因爲我選擇一個解析器(格式檢測)的過程方式。爲了改善這一點,最好是用戶一個工廠模式像這樣的(PHP代碼):

class Parser 
{ 
    protected $raw; 

    public function setRaw($raw) 
    { 
     $this->raw = $raw; 
    } 
} 

class ParserA extends Parser 
{ 
    public function __construct() 
    { 
     echo "ParserA constructor\n"; 
    } 

    public function isValid() 
    { 
     if ($this->raw == "A") 
     { 
      return(true); 
     } 
     return(false); 
    } 
} 

class ParserB extends Parser 
{ 
    public function __construct() 
    { 
     echo "ParserB constructor\n"; 
    } 
    public function isValid() 
    { 
     if ($this->raw == "B") 
     { 
      return(true); 
     } 
     return(false); 
    } 
} 

class ParserFactory 
{ 
    static private $parserClasses = array(); 

    public static function registerParser($parserClassName) 
    { 
     self::$parserClasses[] = $parserClassName; 
    } 

    public static function getParser($raw) 
    { 
     foreach(self::$parserClasses as $parserClass) 
     { 
      $parser = new $parserClass(); 
      $parser->setRaw($raw); 
      if ($parser->isValid()) 
      { 
       return($parser); 
      } 
     } 
    } 
} 

ParserFactory::registerParser("ParserA"); 
ParserFactory::registerParser("ParserB"); 
ParserFactory::getParser("B"); 

回答

5

一個更常見的設計是

public function getParser() 
{ 
    if (FormatAParser::IsRecognizedHeader(this->fn) 
    { 
     return new FormatAParser(this->fn); 
    } 
    if (FormatBParser::IsRecognizedHeader(this->fn) 
    { 
     return new FormatBParser(this->fn); 
    } 
} 

這使用一類,而不是一個對象的方法,以檢查標題。一個明顯的變化是收集列表中的不同解析器,而不是像這樣手動循環它們。這要求能夠將類(不是對象)添加到列表中。

+0

查看我對Jaydel的回答:我認爲這樣會更好呃做一次轉換的東西比做兩次。 – Antoine 2010-12-21 15:18:06

+0

Tim Barrass的組合解釋:非常感謝!我會更新我的問題,添加一些關於工廠模式的內容 – Antoine 2010-12-21 16:06:55

1

我不相信有任何un-OO有關於讓對象理解和評估自己的有效性。你總是可以使isValid方法成爲靜態的,並通過'標準'(在這種情況下是頭部),這樣你就不需要在解析器實例化,直到你知道你需要它。

1

我認爲,這裏的OO-ness來自於你有多個if語句的事實,每個語句都明顯地檢查某種類型的文件(在本例中是一種文件類型),這與我們的概念一致,即應該有一個類來表示每個文件類型;這種切換通常是一種代碼異味,在設計中有些東西不是很正確,但實際上,我認爲你的解決方案是可以的,但是MSalters更好,因爲很難知道解析器會如何工作,因爲文件本身無法爲你自動生成一個類實例。

相關問題