我有一个基类Node
正在做模拟器的繁重工作。我使用相同的基类有一些不同的算法,所以我从NodeA
继承了NodeB
和Node
。还有另一个课程为视觉表现做了艰苦的工作。这些节点能够在没有可视化表示的情况下运行和工作,因此它们位于不同的库项目中。
我无法做到的是,如果你喜欢上课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
}
}
答案 0 :(得分:3)
不是VirtualNode
继承自NodeA
或NodeB
,而是让它使用NodeA或NodeB。
Perfer Composistion over Inheritance总是更好。你要选择更有意义的那个。在这种情况下,组合更有意义,因为明确的继承无法解决您的问题(至少很容易)。
您可以将其实施为Decorator pattern或Strategy 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类。您可以根据要使用的算法在运行时组装它们。