我们有一个不同类型的对象树,它来自一个公共树节点,我们想要编写一个方法来渲染完整的树。我们使用基于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);
}
.
.
.
}
即使这是在基类中完成的,派生的Renderer也只是实现特定的渲染代码,但这不是一个好的OO设计。如果我添加一个新的Tree节点,我需要更改所有渲染器并避免这种情况,我们需要将渲染代码添加到树节点本身,当引入新的渲染器时,再次需要同步。 所以我们有多种树节点和多种渲染器。我们如何设计它以避免类型检查,并避免更改一个类,如果是另一类新类。
答案 0 :(得分:0)
如果您愿意使用同名但不同的类型参数创建多个渲染方法,则可以解决此问题:
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
机制根据node
中RenderNode
的运行时类型选择正确的重载。
(总的来说,这是做与原始代码非常相似的事情 - 除非您不必自己编写所有类型检查代码)
答案 1 :(得分:0)
看看visitor pattern。访问者设计模式是一种将算法与其运行的对象结构分离的方式。
Bacisly你为render alogritm的每个实现创建一个单独的类,并将该类注入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)
{
/*
...
*/
}
}