Правильно ли для объекта отвергать себя? - PullRequest
2 голосов
/ 21 декабря 2010

Я хочу проанализировать несколько форматов файлов.Мне интересно, правильно ли ООП "рисковать", чтобы создать объект даром.

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
        */
    }
}

Спасибо

РЕДАКТИРОВАТЬ
У меня были очень хорошие ответы.Таким образом, объект может проверить свою действительность.Во всяком случае, мой код был не-ООП из-за процедурного способа, которым я выбираю парсер (определение формата).Чтобы улучшить это, лучше использовать фабричный шаблон, подобный этому (код 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");

Ответы [ 3 ]

5 голосов
/ 21 декабря 2010

Более распространенный дизайн -

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

Для проверки заголовка используется класс, а не метод объекта. Очевидным вариантом является сбор различных парсеров в списке, вместо того, чтобы вручную зацикливать их, как это. Для этого требуется возможность добавлять классы (не объекты) в список.

1 голос
/ 21 декабря 2010

Я думаю, что здесь возможно отсутствие единства, потому что у вас есть несколько операторов if, каждое из которых явно проверяет какой-то тип (в данном случае тип файла). Это согласуется с нашим представлением о том, что, вероятно, должен существовать класс, представляющий каждый тип файла; такого рода переключение обычно является запахом кода, что что-то в дизайне не совсем правильно. На практике, однако, я думаю, что ваше решение в порядке, но MSalters лучше, потому что трудно понять, как иначе будет работать парсер, так как сам файл не может автоматически генерировать экземпляр класса для вас.

1 голос
/ 21 декабря 2010

Я не верю, что есть что-то неуместное в том, чтобы объект понимал и оценивал свою действительность.Вы всегда можете сделать метод isValid статическим и передать «критерии» (в данном случае заголовок. Таким образом, вам не нужно создавать экземпляр анализатора, пока вы не узнаете, что он вам нужен.

...