I have an IComposer
interface in my c# project:
public interface IComposer
{
string GenerateSnippet(CodeTree tree);
}
CodeTree
is a base class that contains a List<CodeTree>
of classes that inherit from CodeTree
. For example:
public class VariablesDecleration : CodeTree
{
//Impl
}
public class LoopsDecleration : CodeTree
{
//Impl
}
I can have a few classes that implement IComposer
and in each I have the GenerateSnippet
that loops over the List<CodeTree>
and basically do:
foreach (CodeTree code in tree.Codes)
{
if (code.GetType() == typeof(VariablesDecleration))
{
VariablesDecleration codeVariablesDecleration = (VariablesDecleration) code;
// do class related stuff that has to do with VariablesDecleration
}
else if (code.GetType() == typeof(LoopsDecleration))
{
LoopsDecleration codeLoopsDecleration = (LoopsDecleration) code;
// do class related stuff that has to do with LoopsDecleration
}
}
I have this foreach
and if
statements repeating in each class that implements IComposer
.
I was wondering if there is a better design pattern to handle such a case. lets say tommrow I add a new class that inherits from CodeTree
- I would have to go over all the classes that implement IComposer
and modify them.
I was thinking about the Visitor Design Pattern - but wasn't sure and not exactly sure if and how to implement it. Does Visitor even the right solution for this case?
Move implementation related to the specific classes inside VariablesDecleration
and LoopsDecleration
, providing an abstract implementation in CodeTree
. Then in your loops, simple call that method in CodeTree, without an if...else check.
public class VariablesDecleration : CodeTree
{
//Impl
public void SomeStuff()
{
//... specific to Variables
}
}
public class LoopsDecleration : CodeTree
{
//Impl
public void SomeStuff()
{
//... specific to Loops
}
}
public class CodeTree : ICodeTree
{
void SomeStuff();
}
foreach (CodeTree code in tree.Codes)
{
code.SomeStuff();
}
As per the comments, you might need something like this:
public interface IComposer
{
string DoStuff();
}
public class LoopComposer1 : IComposer
{
string DoStuff(){ .. }
}
public class VariableComposer1 : IComposer
{
string DoStuff(){ .. }
}
public class ComposerCollection
{
private IEnumerable<IComposer> composers;
string GenerateSnippet()
{
foreach(var composer in composers)
{
composer.DoStuff();
}
...
...
}
}
Of course, now the relation has inverted, and your code tree or its creator has to define the composer collection for it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With