我们有一个由不同类型的对象组成的树,这些对象是从一个公共的树节点派生出来的,我们想要编写一个方法来呈现完整的树。我们根据所选的UI使用不同的渲染器。文本渲染器,2d渲染器,3d渲染器。我们的树就是我们的模型,我们不想把渲染代码放在它里面。因此,我们决定创建单独的渲染代码。我们的渲染器有一个方法RenderNode(TreeNode节点),它引用基类TreeNode。因为我们需要处理各种不同类型的节点,所以我们对每个树节点类型进行类型检查并渲染它。
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设计。如果我添加了一个新的树节点,我需要更改所有的渲染器,为了避免这种情况,我们需要向树节点本身添加渲染代码,当引入新的渲染器时,需要再次同步渲染代码。所以我们有多种树节点和多种渲染器。我们如何设计它来避免类型检查,并避免在一个新的类的另一个类的时候改变一个类。
发布于 2017-06-09 14:00:16
如果您愿意创建具有相同名称但不同类型参数的多个呈现方法,则可以解决此问题:
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机制根据RenderNode中node的运行时类型选择正确的重载。
(总体而言,这与原始代码非常相似-除了您不必自己编写所有的类型检查代码)
发布于 2017-06-09 14:21:11
看一看visitor pattern。访问者设计模式是一种将算法从其操作的对象结构中分离出来的方法。
简单地说,您可以为渲染算法的每个实现创建一个单独的类,并将该类注入到TreeNode派生类中。
下面是一个实现的示例:
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)
{
/*
...
*/
}
}https://stackoverflow.com/questions/44450232
复制相似问题