471,321 Members | 1,938 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,321 software developers and data experts.

Inheritance, Specialization, and Factory Classes

Using the dotnet v1.1 framework (so no generics possible). I'd like to
create a bunch of Factory classes that all inherit from a single
abstract base Factory class. Each Factory is responsible for the
creation of objects of a type that inherit from a base class. Factory
is probably the wrong word here, as it's really a persistance class,
but the problem is the same.
Example:
abstract BaseClass
abstract BaseFactory, uses BaseClasses internally, has a bunch of
abstract and virtual methods that are responsible for the actual
implementation:
virtual BaseClass createNew(); //does a bunch of stuff and calls
doCreateNew() to do actual creation
abstract BaseClass doCreateNew();
virtual bool save(BaseClass b); //does a bunch of stuff and calls
doSave() to actually save
abstract bool doSave(BaseClass b);
...
you get the idea.

concrete ClassA extends BaseClass.
concrete ClassAFactory extends BaseFactory, implements doCreateNew,
doSave, etc. Problem is, I'd like this class to only accept instances
of ClassA rather than BaseClass, and I'd like the createNew functions
to return instances of ClassA rather than BaseClass. I know I can use
new on the functions, but that doesn't seem like the right answer as it
doesn't really hide the base functions.

In fact, the problem is a bit deeper then this, as ClassAFactory itself
can require different parameters for the createNew, save, etc.
functions (such as a userId for auditing purposes), and I would like to
truely hide the base functions (current idea is to implement them and
just throw NotImplemented exceptions, but that seems ugly, and it
clutters up my build logs with a bunch of unreachable code detected
messages)

Anyone have any ideas how this type of thing could be / should be done?

Jan 31 '06 #1
4 1900
I'd drop the idea of a BaseFactory completely, because the only way to
implement what you want would be to use the new keywork (or Shadows in
VB) to hide the FactoryBase's Create method and totally rewrite the
method signature.

public classAFactory {
public new Create( int key ) {} // This method totally hides the
FactoryBases's Create method.
}

However, new/Shadows breaks inheritience (by design) and if you find
yourself wanting to use them, you should instead rule out inheritience
completely for those set of classes.

Jan 31 '06 #2
Dropping the BaseFactory leads to alot of code duplication (although
the code will be easier to follow). Most of the implementation code is
the same. For instance, if the Factory (really a persistance class)
used SQL to actually load/save/delete data, the only difference between
the classes would be the actually SQL statement. The logging and data
checking would be the same between classes.

I dunno, I understand that I'm kinda breaking with the purity of
interfaces and inheritance by trying to limit the parameters and return
types, but it still seems logical to me. If you think of inheritance
as specialization rather then extention. I keep thinking this would be
easier if I could use the new generics features in the 2.0 framework,
but the customer wants to stick with 1.1 for now.

Jan 31 '06 #3
Anon,

Perhaps your FactoryBase becomes an internal class, FactoryHelper,
which stores all the code you don't want to duplicate. That way, you
have a good clean design and don't have to worry about duplicating a
lot of code.

Get .Net Reflector sometime (From Lutz Roeder), there are TONS of
internal classes in the .net framework itself that do nothing but
assist the public classes.

HTH
Andy

Jan 31 '06 #4
Actually, I forgot the main reason I want all the Factories to inherit
from a BaseFactory. There is another factory that generates these
factories. The way it works is like this:
DataSource produces Managers which manage Objects. The factories I was
talking about are actually the Managers, each inheriting from a common
base, or implementing a common interface IManager.

DataSource has a function IManager getManagerForType(Type t) that
returns an instance of a TypeTManager that provides the createNew,
save, getById, etc, functions.

This allows objects to locate other classes of objects from the same
DataSource. Example: think of a Student object trying to locate a
Class object (this is not a homework problem, it's just Students and
Classes are a good example). These objects are completely independant
of each other, but it would be nice to be able to have a function like
this in the Class class:

public Student[] getStudents(){
IStudentManager manager =
this.dataSource.getManagerFor(typeof(Student)) as IStudentManager;
return manager.getStudentsForClass(this.class_id);
}

By injecting the DataSource during object creation (hence the
createNew() function), it allows these object to reach back to their
datasource and reference other classes. I like this becauses it allows
me to fully seperate the persistance layer from the business layer.
Each object knows where it came from, and that's all it needs to know,
each DataSource knows what manager is required for each type. I can
have a XMLDataSource, OleDbDataSource, SqlServerDataSource, etc, that
would each have their own Managers (XMLStudentManager,
OleDbStudentManager, etc).

I think this is a good idea, I'm just having a tough time implementing
it as nicely as I'd like. I've got a working implementation, but it's
kinda ugly and requires a bunch of casts and allows things I don't
want.

Jan 31 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

10 posts views Thread by cppaddict | last post: by
5 posts views Thread by Jeff Greenberg | last post: by
3 posts views Thread by Tommi Mäkitalo | last post: by
6 posts views Thread by Dave | last post: by
9 posts views Thread by nicolas.hilaire | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.