Reputation: 1683
I have implementated the Factory Pattern as below.
However, since the individual classes are public, nothing prevents someone from instantiating them directly.
Is this correct? How do I ensure that the concrete classes are only created via the Factory?
namespace MRS.Framework
{
public abstract class DataSource
{
public override string ToString()
{
return "DataSource";
}
}
public class XMLDataSource : DataSource
{
}
public class SqlDataSource : DataSource
{
}
public class CSVDataSource : DataSource
{
public int MyProperty { get; set; }
public override string ToString()
{
return "CSVDataSource";
}
}
}
Factory implementation
namespace MRS.Framework
{
public abstract class DataSourceFactory
{
public abstract DataSource CreateDataSource(DataSourceType datasourcetype);
}
public class CSVDataSourceFactory : DataSourceFactory
{
public CSVDataSourceFactory()
{
}
public override DataSource CreateDataSource(DataSourceType datasourcetype)
{
return new CSVDataSource();
}
}
public class XMLDataSourceFactory : DataSourceFactory
{
public override DataSource CreateDataSource(DataSourceType datasourcetype)
{
return new XMLDataSource();
}
}
public class SqlDataSourceFactory : DataSourceFactory
{
public override DataSource CreateDataSource(DataSourceType datasourcetype)
{
return new SqlDataSource();
}
}
}
Main
static void Main(string[] args)
{
DataSourceFactory datasourcefactory = new CSVDataSourceFactory();
CSVDataSource ds = (CSVDataSource)datasourcefactory.CreateDataSource(DataSourceType.CSVDataSource);
CSVDataSource myds = new CSVDataSource();
Console.WriteLine(ds.ToString());
Console.WriteLine(myds.ToString());
Console.ReadLine();
}
Upvotes: 5
Views: 377
Reputation: 203848
If you want to know how to prevent people from being able to create instances of the datasources you can do it through interfaces. Create an interface for each datasource with all of the method that you want it to expose. Make the class itself internal or a private inner class of the factory (internal is usually appropriate) and the interface public.
If the question is not how to stop people from creating instances but if you should, that's more of a subjective answer. There are a few things to consider:
Upvotes: 2
Reputation: 28338
Yes, your intuition here is correct; if you want to restrict the construction of your CSVDataSourceFactory
class then you have your access modifiers wrong.
However, it's not the access modifier of the class you need to fix, it's the access modifier of the constructor. You should mark the default constructor internal
so that only other classes within your assembly can construct them. You will, of course, have to enforce your own rules within that assembly but since you have complete control over that code, it shouldn't be an issue.
public class XMLDataSource : DataSource
{
internal XMLDataSource() { }
}
public class SqlDataSource : DataSource
{
internal SqlDataSource() { }
}
public class CSVDataSource : DataSource
{
public int MyProperty { get; set; }
internal CSVDataSource() { }
public override string ToString()
{
return "CSVDataSource";
}
}
Upvotes: 6