物体拒绝自己是否正确?

发布于 2024-10-08 12:09:40 字数 2334 浏览 0 评论 0原文

我想解析几种文件格式。我想知道“冒险”免费创建对象是否是正确的 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
        */
    }
}

谢谢

编辑
我有很好的答案。因此,对象可以检查其自身的有效性。无论如何,由于我选择解析器(格式检测)的过程方式,我的代码不是 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");

I want to parse several files formats. I am wondering if it's correct OOP to "take the risk" to create an object for nothing.

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

Thanks

EDIT
I had very good answers. So, it is OK for an object to check its own validity. Anyway, my code was un-OOP because of the procedural way I select a parser (format detection). To improve this, it is better to user a Factory Pattern like this one (PHP code) :

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清君侧 2024-10-15 12:09:40

更常见的设计是

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

使用类而不是对象方法来检查标头。一个明显的变化是收集列表中的不同解析器,而不是像这样手动循环它们。这需要能够将类(而不是对象)添加到列表中。

A more common design is

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

This uses a class, not an object method to check the header. An obvious variation is to collect the different parsers in a list, instead of manually looping over them like this. This requires the ability to add classes (not objects) to a list.

泛滥成性 2024-10-15 12:09:40

我不认为让一个对象理解并评估其自身的有效性有什么不面向对象的地方。您始终可以将 isValid 方法设为静态并传入“条件”(在本例中为标头)。这样,您不必实例化解析器,直到您知道需要它。

I do not believe there is anything un-OO about having an object understand and evaluate its own validity. You could always make the isValid method static and pass in the 'criteria' (in this case the header. That way you don't have to instantiate the parser until you know you need it.

傲鸠 2024-10-15 12:09:40

我认为这里可能的非面向对象性来自于这样一个事实:您有多个 if 语句,每个语句显然都检查某种类型(在本例中是一种文件类型)。这与我们的观念一致,即应该有一个类来代表每种文件类型;这种切换通常是一种代码味道,表明设计中的某些东西不太正确。然而,实际上,我认为你的解决方案是好的,但 MSalters 更好,因为很难知道解析器将如何工作,因为文件本身无法为你自动生成类实例。

I think the possibly un-OO-ness here is coming from the fact you have multiple if statements, each apparently checking for a type of some sort (in this case a type of file). This jibes with our notion that there should probably be a class that represents each file type; this sort of switching is normally a code smell that something in the design isn't quite right. Practically, however, I think your solution is ok, but that MSalters is better, because it's hard to know how else a parser would work, as the file itself can't autogenerate a class instance for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文