When using the “factory” pattern you should only be able to get a valid instance from the factory and NO other way. Thats kind of the point of the pattern – to reduce the number of points at which instances can be created. Normally in Xojo you might have a module with a method that can create instances, and its the only one allowed to do this. The constructors for the classes the factory method can create should be protected or private so they cannot be directly invoked using New outside the module.
Usually it might look something like (note this code will not compile)
Module People
Public Interface IPerson
Public Function GetName() as string
End Interface
Public Class Villager
Implements IPerson
Public Function GetName() as string
return "Village Person"
End Function
Protected Sub Constructor()
End Sub
End Class
Public Class CityPerson
Implements IPerson
Public Function GetName() as string
return "City Person";
End Function
Protected Sub Constructor()
End Sub
End Class
Public Enum PersonType
Rural
Urban
End Enum
Public Function GetPerson(type as PersonType) as IPerson
select case type
case PersonType.Rural
return new Villager()
case PersonType.Urban
return new CityPerson()
else
raise new UnsupportedOperationException
end select
End Function
End Module
An alternative would be to not use an Interface for IPerson but to make it a base class – they end result is similar.
But, you cant do either in Xojo. At least not quite like my code above shows.
If you have a factory method in the module it cannot invoke their constructors. They are only callable by items in the class hierarchy. It has no special means to access the private or protected constructors of the classes it contains.
So you cant easily restrict construction to ONLY the factory method since what you really need is a “module” or “namespace” scope. And that doesn’t exist.
What you need to do is create an INTERFACE for the various classes in the namespace you intend to expose and make the classes in your namespace implement these interfaces. In addition you need to make the interfaces PUBLIC so they can be used outside the module. As well you need to make the classes that implement the interfaces PRIVATE so you can’t actually try and instantiate them outside the module. This has the unfortunate side effect of making it so you can only use the classes in the module via their interfaces. Remember what we really wanted was just to make it so the only legal way to get an instance was to use the factory.
Note that by having to do everything via an interface this means that “properties” are exposed by pairs of getter / setter methods. Fortunately in Xojo this has little semantic impact except that you have to write the code for it.
All code not in the module must use the interfaces as that’s all you have available.
But now because the classes in the module are PRIVATE you can put as many public constructors on them as you desire. They won’t be callable by anything outside of the module so instances cannot be created in ANY way except by calling the factory method in the module.
Module scope would help reduce this work needed to implement the Factory Pattern by making it possible to implement the module’s classes with “module” scoped constructors. This way you could have the factory return any of the parent or subclass instances and you could skip all the interfaces.
A sample of the initial implementation that doesnt work and the fixed version is here