Perhaps it is enough to create a method that serves to visit any object that implements an interface, rather than the final concrete type. Thus, a single abstract method would be responsible for visiting several types of concrete objects that implement that interface, including objects imported via plug-in.
This way it is possible to add more types dynamically, however it would limit the work of the method, which would work on the interface and not on the concrete type... this limitation can be circumvented by making the interface with a method Accept
which takes a Visitor object, and is able to pass sub-objects to Visitor.
Example in C#:
class Concrete
{
}
/// <summary>
/// Interface de plug-in que pode ser visitada por um Visitor.
/// </summary>
interface IPlugin
{
void Accept(Visitor visitor);
}
class Plugin1 : IPlugin
{
public Concrete Concrete { get; set; }
public void Accept(Visitor visitor)
{
visitor.Visit(this.Concrete);
}
}
abstract class Visitor
{
public void Visit(object obj)
{
if (obj is Concrete)
this.Visit(obj as Concrete);
else if (obj is IPlugin)
this.Visit(obj as IPlugin);
}
public abstract void Visit(Concrete concrete);
public virtual void Visit(IPlugin plugin)
{
plugin.Accept(this);
}
}
Hello Miguel. Interesting your solution, but I don’t understand how I can get around the fact that this unique visitor method works on an interface and not on a concrete type.
– Saulo Moura
Everything you want with the concrete type will have to be done through the interface, because the visitor method only knows the interface. For example, if there is a property
Nome
in the plugins and you want to change the name, so this property will have to be in the interfaceIPlugin
and implemented in all concrete classes that implement the same.– Miguel Angelo
But what if I add a new element with particular attributes and want to manipulate them from the implementation of this visit()? No way?
– Saulo Moura
It will not be possible for the visiting method to manipulate parts of the concrete object that it does not know. What you can do is implement in the interface methods to list and manipulate such attributes, via string, or use reflection (ai depends on the language).
– Miguel Angelo