首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >设计模式:我应该在这里使用继承吗?

设计模式:我应该在这里使用继承吗?
EN

Stack Overflow用户
提问于 2019-04-15 22:11:26
回答 1查看 55关注 0票数 0

导言/设置

我正在做一个文本编辑器项目,目前我已经设置了一个可工作的语法高亮符。但我觉得我的设计方法并不能很好地使用可维护的代码。

下面是语法高亮类的声明(不要担心前面有“q”的特定语言类型;这些类型只是由C++的Qt框架定义的):

代码语言:javascript
复制
class Highlighter : public QSyntaxHighlighter
{
    Q_OBJECT

public:

    Highlighter(QTextDocument *parent = nullptr) : QSyntaxHighlighter (parent) {}
    virtual void addKeywords(QStringList keywords);
    virtual void setKeywordFormat();
    virtual void setClassPattern(QRegularExpression classPattern);
    virtual void setClassFormat();
    virtual void setFunctionPattern(QRegularExpression functionPattern);
    virtual void setFunctionFormat();
    virtual void setQuotePattern(QRegularExpression quotePattern);
    virtual void setQuoteFormat();
    virtual void setInlineCommentPattern(QRegularExpression inlineCommentPattern);
    virtual void setInlineCommentFormat();
    virtual void setBlockCommentStartPattern(QRegularExpression blockCommentStart);
    virtual void setBlockCommentEndPattern(QRegularExpression blockCommentEnd);
    virtual void setBlockCommentFormat();
    virtual void addRule(QRegularExpression pattern, QTextCharFormat format);

protected:

    virtual void highlightBlock(const QString &text) override;
    virtual void highlightMultilineComments(const QString &text);

private:

    struct HighlightingRule
    {
        QRegularExpression pattern;
        QTextCharFormat format;
    };

    QVector<HighlightingRule> rules;

    QRegularExpression blockCommentStart;
    QRegularExpression blockCommentEnd;

    QTextCharFormat keywordFormat;
    QTextCharFormat classFormat;
    QTextCharFormat inlineCommentFormat;
    QTextCharFormat blockCommentFormat;
    QTextCharFormat quoteFormat;
    QTextCharFormat functionFormat;
};

我将许多函数声明为虚拟函数,并考虑到了继承。然而,我是否应该使用继承确实是这个问题的核心(稍后会有更多的介绍)。

此外,标头还包括以下不属于类的函数:

代码语言:javascript
复制
Highlighter *cHighlighter(QTextDocument *doc);
Highlighter *cppHighlighter(QTextDocument *doc);
Highlighter *javaHighlighter(QTextDocument *doc);
Highlighter *pythonHighlighter(QTextDocument *doc);

这些函数中的每一个都组合了相应类型的荧光笔。以下是功能定义:

代码语言:javascript
复制
/* Returns a Highlighter object specific to the C language and its grammar and syntax.
 */
Highlighter *cHighlighter(QTextDocument *doc)
{
    QStringList keywords;

    keywords << "\\bauto\\b" << "\\bbreak\\b" << "\\bcase\\b" << "\\bchar\\b" << "\\bconst\\b"
             << "\\bcontinue\\b" << "\\bdefault\\b" << "\\bdo\\b" << "\\bdouble\\b" << "\\belse\\b"
             << "\\benum\\b" << "\\bextern\\b" << "\\bfloat\\b" << "\\bfor\\b" << "\\bgoto\\b"
             << "\\bif\\b" << "\\bint\\b" << "\\blong\\b" << "\\bregister\\b" << "\\breturn\\b"
             << "\\bshort\\b" << "\\bsigned\\b" << "\\bsizeof\\b" << "\\bstatic\\b" << "\\bstruct\\b"
             << "\\bswitch\\b" << "\\btypedef\\b" << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvoid\\b"
             << "\\bvolatile\\b" << "\\bwhile\\b";

    QRegularExpression classPattern("\\b[A-Z_][a-zA-Z0-9_]*\\b");
    QRegularExpression quotePattern("(\".*\")|('\\\\.')|('.{0,1}')");
    QRegularExpression functionPattern("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\()");
    QRegularExpression inlineCommentPattern("//.*");
    QRegularExpression blockCommentStart("/\\*");
    QRegularExpression blockCommentEnd("\\*/");

    Highlighter *highlighter = new Highlighter(doc);
    highlighter->addKeywords(keywords);
    highlighter->setClassPattern(classPattern);
    highlighter->setQuotePattern(quotePattern);
    highlighter->setFunctionPattern(functionPattern);
    highlighter->setInlineCommentPattern(inlineCommentPattern);
    highlighter->setBlockCommentStartPattern(blockCommentStart);
    highlighter->setBlockCommentEndPattern(blockCommentEnd);

    return highlighter;
}


/* Returns a Highlighter object specific to the C++ language and its grammar and syntax.
 */
Highlighter *cppHighlighter(QTextDocument *doc)
{
    Highlighter *cLanguage = cHighlighter(doc);
    QStringList cppOnlyKeywords;

    cppOnlyKeywords <<  "\\basm\\b" << "\\bbool\\b" << "\\bcatch\\b" <<
                        "\\bclass\\b" << "\\bconst_cast\\b" << "\\bdelete\\b" <<
                        "\\bdynamic_cast\\b" << "\\bexplicit\\b" << "\\bfalse\\b" <<
                        "\\bfriend\\b" << "\\binline\\b" << "\\bmutable\\b" <<
                        "\\bnamespace\\b" << "\\bnew\\b" << "\\boperator\\b" <<
                        "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b" <<
                        "\\breinterpret_cast\\b" << "\\bstatic_cast\\b" <<
                        "\\btemplate\\b" << "\\bthis\\b" << "\\bthrow\\b" <<
                        "\\btrue\\b" << "\\btry\\b" << "\\btypeid\\b" << "\\btypename\\b" <<
                        "\\bvirtual\\b" << "\\busing\\b" << "\\bwchar_t\\b";

    cLanguage->addKeywords(cppOnlyKeywords);
    return cLanguage;
}


/* Returns a Highlighter object specific to the Java language and its grammar and syntax.
 */
Highlighter *javaHighlighter(QTextDocument *doc)
{
    QStringList keywords;

    keywords << "\\babstract\\b" << "\\bassert\\b" << "\\bboolean\\b" << "\\bbreak\\b" << "\\bbyte\\b"
             << "\\bcase\\b" << "\\bcatch\\b" << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b" << "\\bcontinue\\b"
             << "\\bdefault\\b" << "\\bdo\\b" << "\\bdouble\\b" << "\\belse\\b" << "\\benum\\b" << "\\bextends\\b"
             << "\\bfinal\\b" << "\\bfinally\\b" << "\\bfloat\\b" << "\\bfor\\b" << "\\bgoto\\b" << "\\bif\\b"
             << "\\bimplements\\b" << "\\bimport\\b" << "\\binstanceof\\b" << "\\bint\\b" << "\\binterface\\b"
             << "\\blong\\b" << "\\bnative\\b" << "\\bnew\\b" << "\\bpackage\\b" << "\\bprivate\\b" << "\\bprotected\\b"
             << "\\bpublic\\b" << "\\breturn\\b" << "\\bshort\\b" << "\\bstatic\\b" << "\\bstrictfp\\b" << "\\bsuper\\b"
             << "\\bswitch\\b" << "\\bsynchronized\\b" << "\\bthis\\b" << "\\bthrow\\b" << "\\bthrows\\b" << "\\btransient\\b"
             << "\\btry\\b" << "\\bvoid\\b" << "\\bvolatile\\b" << "\\bwhile\\b" << "\\btrue\\b" << "\\bfalse\\b" << "\\bnull\\b";

    QRegularExpression classPattern("\\b[A-Z_][a-zA-Z0-9_]*\\b");
    QRegularExpression quotePattern("(\".*\")|('\\\\.')|('.{0,1}')");
    QRegularExpression functionPattern("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\()");
    QRegularExpression inlineCommentPattern("//.*");
    QRegularExpression blockCommentStart("/\\*");
    QRegularExpression blockCommentEnd("\\*/");

    Highlighter *highlighter = new Highlighter(doc);
    highlighter->addKeywords(keywords);
    highlighter->setClassPattern(classPattern);
    highlighter->setQuotePattern(quotePattern);
    highlighter->setFunctionPattern(functionPattern);
    highlighter->setInlineCommentPattern(inlineCommentPattern);
    highlighter->setBlockCommentStartPattern(blockCommentStart);
    highlighter->setBlockCommentEndPattern(blockCommentEnd);

    return highlighter;
}


/* Returns a Highlighter object specific to the Python language and its grammar and syntax.
 */
Highlighter *pythonHighlighter(QTextDocument *doc)
{
    QStringList keywords;

    keywords << "\\band\\b" << "\\bas\\b" << "\\bassert\\b" << "\\bbreak\\b" << "\\bclass\\b" << "\\bcontinue\\b"
             << "\\bdef\\b" << "\\bdel\\b" << "\\belif\\b" << "\\belse\\b" << "\\bexcept\\b" << "\\bFalse\\b"
             << "\\bfinally\\b" << "\\bfor\\b" << "\\bfrom\\b" << "\\bglobal\\b" << "\\bif\\b" << "\\bimport\\b"
             << "\\bin\\b" << "\\bis\\b" << "\\blambda\\b" << "\\bNone\\b" << "\\bnonlocal\\b" << "\\bnot\\b"
             << "\\bor\\b" << "\\bpass\\b" << "\\braise\\b" << "\\breturn\\b" << "\\bTrue\\b" << "\\btry\\b"
             << "\\bwhile\\b" << "\\bwith\\b" << "\\byield\\b";

    QRegularExpression classPattern("\\b[A-Z_][a-zA-Z0-9_]*\\b");
    QRegularExpression quotePattern("(\".*\")|('.*')");
    QRegularExpression functionPattern("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\()");
    QRegularExpression inlineCommentPattern("#.*");
    QRegularExpression blockCommentStart("'''");
    QRegularExpression blockCommentEnd("'''");

    Highlighter *highlighter = new Highlighter(doc);
    highlighter->addKeywords(keywords);
    highlighter->setClassPattern(classPattern);
    highlighter->setQuotePattern(quotePattern);
    highlighter->setFunctionPattern(functionPattern);
    highlighter->setInlineCommentPattern(inlineCommentPattern);
    highlighter->setBlockCommentStartPattern(blockCommentStart);
    highlighter->setBlockCommentEndPattern(blockCommentEnd);

    return highlighter;
}

问题

请注意名为highlightMultilineComments的受保护方法。默认情况下,由于Qt中执行语法突出显示的方式,此方法假定荧光笔的blockCommentStartblockCommentEnd正则表达式不相同。在Python这样的语言中,情况显然不是这样,因为开始和结束注释标记是相同的(三重单引号或双引号)。在这种情况下,函数不能按预期执行。你只需要知道这些。

继承问题

我使highlightMultilineComments方法变为虚拟的,目的是创建一个子类,比如PythonHighlighter,该子类只覆盖定义自定义逻辑的特定函数。理论上,其他语言可以覆盖一切,并自定义它们希望如何设置高亮笔(如果我继承的话)。

但是,如果我要为Python创建一个子类,这意味着我必须为C、C++、Java以及将来想添加的任何其他语言创建一个子类(为了一致性)。这显然比我目前的方法更难管理,因为我的功能只是组装荧光笔。如果我为每种语言添加一个类,源文件的数量就会显著增加。

关于构建器功能的问题

因此,使用构建器函数有其好处。但是,这种方法不允许我重写highlightMultilineComments方法。所以在这方面显然不太理想。

问题

我如何利用继承的好处--能够根据语言覆盖highlightMultilineComments之类的方法--而不牺牲“构建器函数”的相对可维护性?

--我考虑过的其他事情--

我还考虑过添加像highlightSymmetricMultilineComments这样的函数。然后,highlightMultilineComments可以检查blockCommentStartblockCommentEnd是否具有相同的正则表达式。如果它们有相同的模式,则函数将简单地调用其对称变量。

这带来了一个明显的问题--考虑到并不是所有语言都有对称的多行注释(Python是文本编辑器目前支持的唯一注释),这在高亮笔中是没有意义的。

EN

回答 1

Stack Overflow用户

发布于 2019-04-15 23:27:50

考虑添加一个commentHighlighter成员变量,该变量表示实际高亮显示的函数:

代码语言:javascript
复制
std::function<void(Highlighter&, const QString&)> commentHighlighter;

然后我们可以编写highlightMultilineComments,以便它调用这个成员变量:

代码语言:javascript
复制
void highlightMultilineComments(const QString &text) 
{
    // If the class has a valid commentHighlighter, use that
    if(commentHighlighter) 
    {
        commentHighlighter(*this, text); 
    } 
    else //Otherwise, use the default implementation
    {
        // Default implementation
    }
}

如果您需要对一种语言进行专门的突出显示,那么您只需提供一个函数来进行突出显示,而不必为它创建一个新的类。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55697892

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档