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

时间:2016-01-13 17:37:05

标签: c# object-oriented-analysis

我有一个基类Node正在做模拟器的繁重工作。我使用相同的基类有一些不同的算法,所以我从NodeA继承了NodeBNode。还有另一个课程为视觉表现做了艰苦的工作。这些节点能够在没有可视化表示的情况下运行和工作,因此它们位于不同的库项目中。

我无法做到的是,如果你喜欢上课VisualNode我只能在我运行视觉应用程序的时候从其中一个类继承,而我实际上是在初始化VisualNode的实例开始工作。我想让用户能够选择要运行的算法。

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

以下是我的课程:

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
    }
}

还有另一个类应该能够表现得像这两个类:

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
    }
}

3 个答案:

答案 0 :(得分:3)

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

Perfer Composistion over Inheritance总是更好。你要选择更有意义的那个。在这种情况下,组合更有意义,因为明确的继承无法解决您的问题(至少很容易)。

您可以将其实施为Decorator patternStrategy pattern。第一种方法VirtualNode将继承Node并包装另一个Node。 Latter不继承自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。但是可视化工具保持不变。

答案 1 :(得分:1)

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

  

我有一些使用相同基类的不同算法,所以我从Node继承了NodeA和NodeB

答案 2 :(得分:0)

战略模式的另一次投票。它看起来像这样,我想(我的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类或NodeB类。您可以根据要使用的算法在运行时组装它们。