首页 > 解决方案 > 赋予 C# 类模块化功能

问题描述

我有一个类 Node 正在操作我的 Person 类的实例。具有最少功能的基类如下所示:

public class Node
{
    //attributes
    protected readonly int steps;
    protected readonly int angleDeltaQ;

    //constructor
    public Node(int steps, int angleDeltaQ)
    {
        this.steps = steps;
        this.angleDeltaQ = angleDeltaQ;
    }

    //methods
    public virtual int UpdateMe(Person me)
    {
        me.angleQ = QMath.RadLimitQ(me.angleQ + angleDeltaQ);
        me.xQ += QMath.CosQ(me.angleQ, me.speedRev);
        me.zQ += QMath.SinQ(me.angleQ, me.speedRev);
        me.steps--;
        if (me.steps == 0) return (int)NodeFeedback.targetReached;                
        else return (int)NodeFeedback.notFinished;
    }
    public virtual void AssignMe(Person me)
    {
        me.steps = steps << me.speedRev;
    }
}

我离开了 Person 类,因为描述我的问题并不重要。只需要知道Person有一个Node属性,调用一次Node的Assign方法,然后定期更新。

现在 Node 可能还可以做很多其他的事情。

例如在 Update 方法中,它也应该改变 me.yQ 的值。为此,它需要额外的属性并且需要 Update 方法中的额外代码。

对于 Person 实例,它的 Node 属性到底发生了什么并不重要,只要它可以调用它的两个方法即可。

我现在的问题是,Node 类有 8 个附加功能。如果我为每个组合创建一个 Node 的子类,它会变得非常大。

我的问题是,有没有一种整洁的方法来做到这一点?我计划有很多节点的实例,所以我只希望它包含这个特定节点需要的属性和方法。

标签: c#inheritance

解决方案


你应该使用访问者模式

public abstract class Node
{
    //attributes
    protected readonly int steps;
    public readonly int angleDeltaQ;
    private IUpdateVisitor updateVisitor;

    protected  Node():this(new DefaultUpdateVisitor())
    {

    }
    protected  Node(IUpdateVisitor visiter)
    {
        updateVisiter = visiter;
    }
    //constructor
    public Node(int steps, int angleDeltaQ)
    {
        this.steps = steps;
        this.angleDeltaQ = angleDeltaQ;
    }

    //methods
    public virtual int UpdateMe(Person me)
    {
            updateVisitor.UpdateMe(this,me);
    }
    public virtual void AssignMe(Person me)
    {
        me.steps = steps << me.speedRev;
    }
}



public interface IUpdateVisitor
{
     int UpdateMe(Person me);
}


public class DefaultUpdateVisitor : IUpdateVisitor
{
    public  int UpdateMe(Node node, Person me)
    {
        me.angleQ = QMath.RadLimitQ(me.angleQ + node.angleDeltaQ);
        me.xQ += QMath.CosQ(me.angleQ, me.speedRev);
        me.zQ += QMath.SinQ(me.angleQ, me.speedRev);
        me.steps--;
        if (me.steps == 0) return (int)node.NodeFeedback.targetReached;                
        else return (int)node.NodeFeedback.notFinished;
    }
}


public class AotherUpdateVisitor: IUpdateVisitor
{
 public  int UpdateMe(Node node, Person me)
 {
     .....
 }   
}

推荐阅读