首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当使用公共基类作为函数参数时,如何处理依赖类并避免类型检查?

当使用公共基类作为函数参数时,如何处理依赖类并避免类型检查?
EN

Stack Overflow用户
提问于 2017-06-09 13:55:04
回答 2查看 90关注 0票数 0

我们有一个由不同类型的对象组成的树,这些对象是从一个公共的树节点派生出来的,我们想要编写一个方法来呈现完整的树。我们根据所选的UI使用不同的渲染器。文本渲染器,2d渲染器,3d渲染器。我们的树就是我们的模型,我们不想把渲染代码放在它里面。因此,我们决定创建单独的渲染代码。我们的渲染器有一个方法RenderNode(TreeNode节点),它引用基类TreeNode。因为我们需要处理各种不同类型的节点,所以我们对每个树节点类型进行类型检查并渲染它。

代码语言:javascript
复制
void RenderNode(TreeNode node) { 
    if(node is NoEditNode){
        // call Derive class RenderEditNode
        RenderEditNode(node);
    }
    else if (node is PersonNode){
        // call Derive class RenderPersonNode
        RenderPersonNode(node);
    }
    else if (node is AssetNode){
        // call Derive class RenderAssetNode
        RenderAssetNode(node);
    }
    .
    .
    .
}

即使这是在基类中完成的,派生渲染器只实现特定的渲染代码,这也不是一个好的OO设计。如果我添加了一个新的树节点,我需要更改所有的渲染器,为了避免这种情况,我们需要向树节点本身添加渲染代码,当引入新的渲染器时,需要再次同步渲染代码。所以我们有多种树节点和多种渲染器。我们如何设计它来避免类型检查,并避免在一个新的类的另一个类的时候改变一个类。

EN

回答 2

Stack Overflow用户

发布于 2017-06-09 14:00:16

如果您愿意创建具有相同名称但不同类型参数的多个呈现方法,则可以解决此问题:

代码语言:javascript
复制
public void RenderNode(TreeNode node) { 
    RenderNodeInternal(node as dynamic);
}

private void RenderNodeInternal(AssetNode node) {
    .
    .
    .
}

private void RenderNodeInternal(NoEditNode node) {
    .
    .
    .
}

private void RenderNodeInternal(PersonNode node) {
    .
    .
    .
}

这利用dynamic机制根据RenderNodenode的运行时类型选择正确的重载。

(总体而言,这与原始代码非常相似-除了您不必自己编写所有的类型检查代码)

票数 0
EN

Stack Overflow用户

发布于 2017-06-09 14:21:11

看一看visitor pattern。访问者设计模式是一种将算法从其操作的对象结构中分离出来的方法。

简单地说,您可以为渲染算法的每个实现创建一个单独的类,并将该类注入到TreeNode派生类中。

下面是一个实现的示例:

代码语言:javascript
复制
public interface IRenderer
{
    void Render(TreeNode node);
}

class NoEditNode : TreeNode
{
    IRenderer renderer = new RenderEditNode();
    public void Render()
    {
        renderer.Render(this);
    }
}

class RenderEditNode :  IRenderer
{
    public void Render(TreeNode node)
    {
    /*  
    ...
    */
    }
}


class PersonNode : TreeNode
{
    IRenderer renderer;

    public PersonNode(IRenderer renderer)
    {
        this.renderer = renderer;
    }

    public void Render()
    {
        renderer.Render(this);
    }
}

class RenderPersonNode :  IRenderer
{
    public void Render(TreeNode node)
    {
        /*  
        ...
        */
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44450232

复制
相关文章

相似问题

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