I have a Factory. I do not want to allow classes that this factory produces to be instantiated outside of the factory. If I make them abstract, static, or give them private constructors then they won't be instantiable at all! Is this a language restriction or what?
I don't want to allow this
var awcrap = new Extrude2013 (); // BAD !!!
awcrap.extrudify (); // I don't want to allow this
Rest of code:
using System;
namespace testie
{
public enum ExtrudeType { Extrude2013, Extrude2014 }
public interface IExtrudeStuff {
void extrudify();
}
public class Extrude2013 : IExtrudeStuff {
public void extrudify(){
Console.WriteLine ("extrudify 2013");
}
}
public class Extrude2014 : IExtrudeStuff {
public void extrudify(){
Console.WriteLine ("extrudify 2014");
}
}
public static class ExtrudeFactory {
public static IExtrudeStuff Create(ExtrudeType t) {
switch (t) {
case ExtrudeType.Extrude2013: return new Extrude2013 ();
case ExtrudeType.Extrude2014: return new Extrude2014 ();
default: return null;
}
}
}
class MainClass {
public static void Main (string[] args) {
// Now for the pretty API part
var o = ExtrudeFactory.Create (ExtrudeType.Extrude2013);
o.extrudify ();
var p = ExtrudeFactory.Create (ExtrudeType.Extrude2014);
p.extrudify ();
var awcrap = new Extrude2013 (); // BAD !!!
awcrap.extrudify (); // I don't want to allow this
}
}
}
You can't completely disallow this. Whether or not it's a language "restriction" would be a matter of opinion, but there are things that you could consider:
internal
. This will allow any type within the declaring assembly to call the constructor, but nothing outside the assembly. This would mean that any code you write in that assembly to be responsible for calling the factory, and it also means that you could not declare subtypes of the class in another assembly, since it would be unable to call the constructor.internal
(or even private
as a subclass of the factory, since it would never be referenced outside of the factory) type that implements the abstract class or interface.DataTable
class works. While the constructor could still be called, the user would have to pass in null
for the value and it would at least be obvious that they shouldn't be doing this.The whole point of Factory Pattern
is that only the Factory knows how to choose and make an object and it only exposes the instantiated object's functionality through an interface not a concrete class. Making the object's constructor private fails because Factory
itself cannot instantiate it.
Solution:
1- Define an interface
class which all types of the Extrude20XX
classes implement it such as IExtrudeStuff
.
2- Wrap the Extrude20XX
classes inside the class of Factory
as private nested classes.
3- Implement the interface IExtrude
in all the ExtrudeXX
classes.
4- Write a (static) Create (t)
method like:
public static class ExtrudeFactory {
public static IExtrudeStuff Create(ExtrudeType t) {
{
switch (t) {
case ExtrudeType.Extrude2013: return new Extrude2013 ();
case ExtrudeType.Extrude2014: return new Extrude2014 ();
default: return null;
}
}
}
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