2010-12-21 4 views
2

여러 파일 형식을 구문 분석하고 싶습니다. 그것은 OOP가 "위험을 무릅 쓰고"객체를 만들지 않을지 궁금합니다.개체가 자기를 거부하는 것이 맞습니까?

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이었습니다.

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); 
    } 
} 

입니다 :이 문제를 개선하기 위해,이 같은 팩토리 패턴 (PHP 코드) 사용자에게 더 나은 헤더. 분명한 차이점은 목록에서 다른 파서를 수동으로 반복하는 대신 이러한 파서를 수집하는 것입니다. 이를 위해서는 클래스가 아닌 객체를 목록에 추가 할 수 있어야합니다.

+0

Jaydel에게 내 대답보기 : 나는 그것이 변환 작업을 한 번 수행하는 것보다 두 번 수행하는 것이 좋습니다. – Antoine

+0

Tim Barrass와 결합 된 설명 : 대단히 감사합니다! 공장 패턴 – Antoine

+0

+1에 대한 몇 가지 내용을 추가하기 위해 질문을 업데이트합니다. 이는 책임을 분리하는 더 좋은 일을하는 것처럼 보입니다. – TrueWill

1

나는 개체가 자신의 타당성을 이해하고 평가하는 것에 대해 uno-OO가 있다고 생각하지 않습니다. 항상 isValid 메서드를 정적으로 만들고 'criteria'를 전달할 수 있습니다 (이 경우 헤더가 필요합니다.) 당신이 필요하다는 것을 알기 전까지는 파서를 인스턴스화 할 필요가 없습니다.

+0

이것은 청소기, 감사합니다! 하지만 ... 유효성을 검사하기 위해 일부 읽기/변환 작업을해야합니다. 객체가 유효한 경우 나중에 사용됩니다 (예 : UTF8에서 ISO8859로 변환). 유효성 확인을 위해 한 번이 아니라 한 번, 개체가 올바른 경우 (올바른 파일 형식) 구문 분석을 한 번 수행하는 것을 선호합니다. – Antoine

1

나는 아마도 un- OO-ness는 여러 개의 if 문을 가지고 있는데, 각 문은 일종의 유형 (이 경우에는 파일 유형)을 확인하는 것입니다. 이것은 각 파일을 나타내는 클래스가 있어야한다는 개념과 일치합니다. 이런 종류의 전환은 일반적으로 코드의 냄새가 나는데, 디자인의 어떤 부분이 적절하지 않다는 것입니다. 그러나 실제로는 솔루션이 좋다고 생각하지만, 구문 분석기가 어떻게 작동하는지 알기가 쉽지 않기 때문에 MSalters가 더 좋습니다. , 파일 자체가 당신을 위해 클래스 인스턴스를 자동 생성 할 수 없기 때문에.

관련 문제