我創建了一個庫來解析不同類型的數據。這就是圖書館的使用方式。正確使用工廠方法/模式和動態加載
$parser = DataParser::factory($text);
$data = $parser->parse();
foreach($data as $name=>$datum)
echo "name: $name\nData: ".$datum."\n";
這裏$data
是NamedDataCollection
一個實例。這裏是類定義
interface Parsable{
// @returns NamedDataCollection
function parse();
// @returns bool. True if it can parse the data.
function can_parse();
}
class AParser implements Parsable{
public function parse(){
$this->check_header();
$this->check_content();
$this->parse_content();
...
}
public function can_parse(){
$this->check_header();
$this->check_content();
...
}
}
class BParser implements Parsable{
public function parse(){
...
}
public function can_parse(){
...
}
}
class ParserRegistry{
// @param $dir path where all the parsers are stored
public function __construct($dir){
}
// @returns all the available parsers by scanning files.
public function get(){
}
}
class DataParser{
public function factory($data){
$instance = null;
$pr= new ParserRegistry("/some/path");
foreach($pr->get() as $pname){
$rc = new ReflectionClass($pname);
$instance = $rc->newInstance($data);
if($instance->can_parse())
return $instance;
}
throw new ParserException("No parser found", 1);
}
}
它是正確的工廠方法的用法?
有一件令我煩惱的事情是can_parse
方法。 似乎有很多解析器的實例是爲了測試它是否可以解析文本而創建的。有沒有更好的方法來做到這一點?我知道我可以使用靜態方法。但大多數解析器使用parse
方法的某些部分(請參閱AParser
定義)。如果我將其設爲靜態,則不能使用這些方法。
注意:示例代碼代表我遵循的模式。但類名和場景僅僅是一個例子。爲示例提供現成的解決方案並不能解決我真正的問題。
通過注入一個策略對象來查找這些對象,可以間接地找到匹配的解析器。這並不能回答你的問題,可能只是告訴你如何在稍後移除'can_parse'依賴。 http://en.wikipedia.org/wiki/Strategy_pattern - 但是你不應該在你的解析器中引入太多的邏輯。如果他們不能解析,他們可能會拋出一個解析異常,但除此之外,他們不能說他們是否可以解析。製作一些元信息,如content-type,以便解析器解析。 – hakre 2013-03-03 09:59:23