运行 多种算法的面向对象设计

Object oriented design for running multiple algorithms

我有一个基地 class Node 在做模拟器的繁重工作。我有一些使用相同基数 class 的不同算法,所以我从 Node 继承了 NodeANodeB。还有另一个 class 负责视觉表示。这些节点能够 运行 并在没有视觉表示的情况下工作,因此它们位于不同的库项目中。

我做不到的是,如果你喜欢 class VisualNode 我一次只能继承 class 中的一个 运行ning 我的可视化应用程序,我实际上初始化了 VisualNode 的实例以启动作业。我想提供用户能够 select 哪个算法到 运行。

在这种情况下,正确的设计是什么?请记住虚拟妓女的方法。

以下是我的 classes:

public abstract class Node
{
    protected abstract void UserDefined_ReceiveMessageProcedure ( Message m );

    public virtual void VisualizeMessage ( Message m )
    {
        /// hooker method for visual interfaces - empty block in this class will be overriden in derived class
    }
}

public class NodeA : Node
{
    protected override void UserDefined_ReceiveMessageProcedure ( Message receivedMessage )
    {
        /// real implementation lies here
        ....
        /// VisualizeMessage is called in here
    }
}

public class NodeB : Node
{
    protected override void UserDefined_ReceiveMessageProcedure ( Message receivedMessage )
    {
        /// real implementation lies here
        ....
        /// VisualizeMessage is called in here
    }
}

还有另一个 class 应该能够像这两种行为一样:

public class VisualNode : NodeA // NodeB 
{
    public Brush NodeColor { get; set; }
    ....

    public VisualNode ( ... )
    {
        /// some setup
    }

    public bool OnIt ( Point p )
    {
        /// some checks
    }
    public void Draw ( ... )
    {
        /// draw it
    }

    public override void VisualizeMessage ( AsyncSimulator.Message m )
    {
        /// visualizing the message
        /// this method is called via superclass
    }
}

Strategy pattern 看起来很适合您的情况。它定义了一系列算法,封装了每一个算法,并使它们可以互换。策略让算法独立于使用它的客户而变化。所以这种方法将帮助你

I have some different algorithms using the same base class, So I have inherited NodeA and NodeB from Node

而不是VirtualNode继承自NodeANodeB,让它使用NodeA或NodeB。

Perfer Composition 总是比 Inheritance 更好。你必须选择一个更有意义的。在这种情况下,组合更有意义,因为显然继承不能解决您的问题(至少很容易)。

您可以将其实现为 Decorator pattern or Strategy pattern。使用第一种方法 VirtualNode 将从 Node 继承并包装另一个 Node 。后者不继承自 Node 但使用 Node.

甚至更好,只需扔掉 VisualNode 并向 Node 注入一个 Visualizer(策略模式)。

public abstract class Node
{
    public IMessageVisualizer MessageVisualizer { get; set; }
    protected abstract void UserDefined_ReceiveMessageProcedure(Message m);
    protected void VisualizeMessage(Message m)
    {
        MessageVisualizer.Visualize(m);
    }
}

public interface IMessageVisualizer
{
    void Visualize(Message m);
}

public class MessageVisualizer : IMessageVisualizer
{
    public Brush NodeColor { get; set; }

    public void Visualize(Message m)
    {
        /// visualizing the message
    }

    public bool OnIt()
    {
        /// some checks
    }
    public void Draw()
    {
        /// draw it
    }
}

您的 NodeA 和 NodeB 保持不变。您可以将其用作

Node node = new NodeA();
node.MessageVisualizer = new MessageVisualizer();
node.DoSomethingThatMightVisualize();

当你不想可视化时,你可以像下面这样提供一个空的 MessageVisualizer 实现

public class NullVisualizer : IMessageVisualizer
{
    public void Visualize(Message m)
    {
        //Don't visualize
    }
}

Node node = new NodeA();
node.MessageVisualizer = new NullVisualizer();//don't visualize
node.DoSomethingThatMightVisualize();

现在您可以根据用户的选择创建 NodeA 或 NodeB。但可视化工具保持不变。

再次投票给策略模式。它看起来像这样,我想(我的 C# 很生疏):

public interface IVisualizeMessageStrategy
{
    void VisualizeMessage(Message m);
}

public class Node
{
    public IVisualizeMessageStrategy VisualizeMessageStrategy ( Message m ) { get; set; }

    protected override void UserDefined_ReceiveMessageProcedure ( Message receivedMessage )
    {
        /// real implementation lies here
        ....
        /// VisualizeMessage is called in here
        this.VisualizeMessageStrategy.VisualizeMessage(receivedMessage);
    }
}

使用方法:

Node nodeA = new Node();
nodeA.VisualizeMessageStrategy = new InstanceOfAlgorithmOneAsAClass();

Node nodeB = new Node();
nodeB.VisualizeMessageStrategy = new InstanceOfAlgorithmTwoAsAClass();

您不需要 NodeA class 或 NodeB class。您 assemble 根据您要使用的算法在运行时使用它们。