假设我们有一个包含以下XML的文件:
<document>
<tagA />
<tagB />
<tagC />
<tag1 />
<tag2 />
<tag3 />
<custom1/>
<custom2/>
</document>
并假设我们有一个解析器对象来扫描文件。对于文件中找到的每个标记,解析器调用处理程序对象的相应方法:
class Handler{
function tagA(){ ... }
function tabB(){ ... }
function tagC(){ ... }
function tag1(){ ... }
function tag2(){ ... }
function tag3(){ ... }
function custom1(){ ... }
function custom2(){ ... }
}
现在,假设我们要构建一个框架来处理上述类型的文件。为了确保代码的可重用性,我们可以将上面的类拆分为不同的(更专业的)类:
class LettersHandler{
function tagA(){ ... }
function tabB(){ ... }
function tagC(){ ... }
}
class NumbersHandler{
function tag1(){ ... }
function tag2(){ ... }
function tag3(){ ... }
}
为了编写上述文件的处理程序,程序员可以利用框架并仅实现缺少的方法(使用OOP继承):
class Handler extends LettersHandler, NumbersHandler{
function custom1(){ ... }
function custom2(){ ... }
}
根据文件的内容,程序员可能只选择从两个类继承(如上例所示)或者不继承。
现在,假设框架支持许多预构建处理程序:
class LettersHandler{ ... }
class NumbersHandler{ ... }
class SymbolsHandler{ ... }
etc...
如果编程语言支持多重继承,程序员可以继承框架提供的一个或多个类来处理特定文件(根据文件中包含的标签)。
现在,我的问题是:
如果编程语言不支持多重继承但只支持单继承,那么实现上述情况的最佳方法是什么?
使用多重继承有一种简单的方法吗?
我已经读过多重继承通常被认为是一种不好的做法,但我真的无法理解如何在不使用它的情况下实现上述情况。
答案 0 :(得分:0)
更改解析器,使其接受一个处理程序数组而不是一个处理程序,并让它依次为每个标记调用每个处理程序。如果处理程序无法处理标记(通过测试方法的存在,或者通过基类的方法返回一些“未实现的”sigil值),则调用下一个处理程序。
如果无法修改解析器,请实现一个新的处理程序,它接受一个处理程序数组并委托给它们,就像它是上面修改过的解析器一样。
这实质上是将程序的类型从程序的类型转移到程序数据中的结构。
答案 1 :(得分:0)
创建一个名为TagHandler
的基类。
// A C++ incarnation of such a class.
class TagHandler
{
virtual processTag(std::string const& tagName,
..., // Any additional arguments that makes sense
) = 0;
};
为客户提供基于标签名称注册TagHandler
的机制。制定一些策略决策,决定如何处理为给定标记名称注册处理程序的多个客户端。你想提出例外吗?最后一个赢了吗?你允许多个TagHandler吗?
class TagProcessor
{
public:
static void registerTagHandler(std::string const& tagName,
TagHandler* tagHandler)
{
// Do the needful to register the TagHandler based on policy.
}
};
提供一个在上面的类中以黑盒方式处理标签的功能。
class TagProcessor
{
public:
static void processTag(std::string const& tagName,
..., // Any additional arguments that makes sense
)
{
// Look for the TagHandler(s) given the tag name.
// If found, call the processTag() function.
// Deal with non-existing TagHandler.
}
};
创建TagHandler
的子类型以处理各种标记。
class TagAHandler : public TagHandler
{
public:
virtual processTag(std::string const& tagName,
...)
{
// Do the needful to process the tag
}
};
注册TagHandler
以处理“tagA”
TagProcessor::register("tagA", new TagHandler());
在解析器代码中调用TagProcessor::processTag
。