Factory method question

J

jonathan.broderick

I'm needing a little bit of clarity on using the factory design
method.

Lets say I have two concrete classes that implement an interface. Then
I have two factories that instantiate objects of that type. I would
like to have the two factories adhere to a common interface for
creating the objects but the problem is that each object requires
different parameters for the constructors.

I could remove the different parameters and create common method
signatures but then I am forced to have the calling class finish
creating the object which seems dumb.

The other thing I was thinking is passing in a "params" of
Dictionary<string,object> objects that correspond to the other fields
required for creating the object. Does this defeat the factory method?

Thanks!
 
P

Paul E Collins

Lets say I have two concrete classes that implement an interface. Then
I have two factories that instantiate objects of that type. I would
like to have the two factories adhere to a common interface for
creating the objects but the problem is that each object requires
different parameters for the constructors.

I think you want the "abstract factory pattern", with your two factories
inheriting from the same common abstract base class rather than
implementing the same interface.

This way, you can have a protected constructor in the base class and
whatever public constructors you want in your factory classes.

Eq.
 
S

sloan

Basically, I look at the factory as:

It needs all pieces of information that it needs to make the decision on
which concrete object to return.
It needs all pieces of information that any concrete constructor needs.


So pass in the superset of objects you need to pass to the constructors, and
I guess each concrete uses the subset it needs.

I don't like that scenario, but I can't necessarily say its wrong either.

Sloan
....
http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!126.entry
Understanding the Simple Factory
 
J

jonathan.broderick

I think you want the "abstract factory pattern", with your two factories
inheriting from the same common abstract base class rather than
implementing the same interface.

This way, you can have a protected constructor in the base class and
whatever public constructors you want in your factory classes.

Eq.

Okay. So if I went this route, I would be calling the factory classes
directly with the parameters I need. I was hoping to avoid programming
directly to the factory instances and rather to an interface or
abstract class. Is that correct or am I missing something?
 
J

jonathan.broderick

So pass in the superset of objects you need to pass to the constructors, and
I guess each concrete uses the subset it needs.


Thats what I was thinking using the params keyword but it doesnt seem
very elegant. Maybe I'm wrong.
 
P

Peter Duniho

Thats what I was thinking using the params keyword but it doesnt seem
very elegant. Maybe I'm wrong.

Your question is a bit vague. But assuming I understand what you're
trying to do, I don't think your proposed solution is necessarily all that
bad.

Personally, I find the factory pattern a bit awkward regardless. So
equivocating as to whether having a variable-length parameter list is
inelegant seems pointless. :) Regardless, whatever you think of the
elegance of the factory pattern, it's there to solve a specific issue and
if it makes sense for the same factory to instantiate different types that
don't use the same parameter lists for their constructors, I don't think
it's a bad idea to make the factory flexible enough to built the
constructor parameter lists dynamically.

I'm not sure you need a Dictionary though. Why not just insist that the
parameter list passed in needs to match the parameter list required for
the constructor? Then you can just use the same parameter list.

Finally, I'll note that the fact that you have these different classes
that don't use the same parameter list for construction _might_ be a hint
that using the same factory to create instances of those classes isn't the
right approach. Again, without more specifics it's hard to say. But it's
something to consider.

Pete
 
J

jonathan.broderick

Your question is a bit vague. But assuming I understand what you're
trying to do, I don't think your proposed solution is necessarily all that
bad.

Personally, I find the factory pattern a bit awkward regardless. So
equivocating as to whether having a variable-length parameter list is
inelegant seems pointless. :) Regardless, whatever you think of the
elegance of the factory pattern, it's there to solve a specific issue and
if it makes sense for the same factory to instantiate different types that
don't use the same parameter lists for their constructors, I don't think
it's a bad idea to make the factory flexible enough to built the
constructor parameter lists dynamically.

I'm not sure you need a Dictionary though. Why not just insist that the
parameter list passed in needs to match the parameter list required for
the constructor? Then you can just use the same parameter list.

Finally, I'll note that the fact that you have these different classes
that don't use the same parameter list for construction _might_ be a hint
that using the same factory to create instances of those classes isn't the
right approach. Again, without more specifics it's hard to say. But it's
something to consider.

Pete

Pete,
Thanks I think I'm using factories incorrectly in this case. I'm not
creating a family of related objects that are depending upon each
other, I'm pretty much just creating single or multiple instances of
one type of object.

Where I was getting confused is that I have multiple subclasses that I
may need to create but I want to have a single factory call create
them all for me. Its confusing, i know but I think i'm settled now.
Thanks!
 
P

Paul E Collins

I was hoping to avoid programming directly to the factory instances
and rather to an interface or abstract class. Is that correct or am I
missing something?

Yes, my suggestion means you'd be programming to concrete classes.

Could you post a short, simplified version of your code, or at least
explain what you're trying to model? Otherwise, it's hard to tell what
approach might be suitable.

Eq.
 
J

jonathan.broderick

Yes, my suggestion means you'd be programming to concrete classes.

Could you post a short, simplified version of your code, or at least
explain what you're trying to model? Otherwise, it's hard to tell what
approach might be suitable.

Eq.

The application I'm creating is a web application. I would guess 90%
of the processing is loading/saving/deleting/updating from an SQL
database. So there's not much processing going on.

Here's some sample code thats sort of like my problem:

public interface IConditional
{
bool IsMatch(string[] data);
}

public class FieldConditional : IConditional
{
public FieldConditional(IField field)
{
... code
}

bool IsMatch(string[] data)
{
... code
}
}

public class DateConditional : IConditional
{
public FieldConditional(DateTime date)
{
... code
}

bool IsMatch(string[] data)
{
... code
}
}


These objects (FieldCondtional and DateConditional) are saved in the
database with a unique
ID between them. I know I can do this:

IConditional c = ConditionalFactory.Load(id);

Is there a way i could do something like this:

IConditional c = ConditionalFactory.Create(<data>);

That way I let the Factory know which object to create and how. I Dont
want to have to do soemthing like this:

IConditional c = ConditionalFactory.CreateField(<data>);
or...
IConditional c = ConditionalFactory.CreateDate(<data>);

The creating part I'm not so sure how to do.
 
P

Peter Duniho

[...]
Is there a way i could do something like this:

IConditional c = ConditionalFactory.Create(<data>);

That way I let the Factory know which object to create and how. I Dont
want to have to do soemthing like this:

IConditional c = ConditionalFactory.CreateField(<data>);
or...
IConditional c = ConditionalFactory.CreateDate(<data>);

The creating part I'm not so sure how to do.

Is "<data>" typed at the point that you'd call that code? Or is it some
generic blob of data? If it's typed, then you just need overloads for the
Create() method for each type. If it's a generic blob of data, you'll
need to turn that into the appropriate type to pass to a constructor,
which you can do inside the Create() method. In fact, this is a typical
use of a factory: having the factory do the data analysis to determine
what type to return.

What that analysis would be depends on your exact situation. Without more
information, it's hard to say how the exact implementation would look.
But there's no fundamental reason you can't do it that way.

Pete
 
J

jonathan.broderick

[...]
Is there a way i could do something like this:
IConditional c = ConditionalFactory.Create(<data>);
That way I let the Factory know which object to create and how. I Dont
want to have to do soemthing like this:
IConditional c = ConditionalFactory.CreateField(<data>);
or...
IConditional c = ConditionalFactory.CreateDate(<data>);
The creating part I'm not so sure how to do.

Is "<data>" typed at the point that you'd call that code? Or is it some
generic blob of data? If it's typed, then you just need overloads for the
Create() method for each type. If it's a generic blob of data, you'll
need to turn that into the appropriate type to pass to a constructor,
which you can do inside the Create() method. In fact, this is a typical
use of a factory: having the factory do the data analysis to determine
what type to return.

What that analysis would be depends on your exact situation. Without more
information, it's hard to say how the exact implementation would look.
But there's no fundamental reason you can't do it that way.

Pete

Yes at this point <data> is NOT typed but rather a generic blob of
data. The data would come from a source (like a user or database). I
was imagining it being an associative array of some sort that could
easily be accessed through well known keys.

I was concerned there was a "better" way of doing things but every
example I have seen on Google has only been simple cases. Granted,
"better" is in the eye of the beholder (or application for that
matter) but I want to make sure I'm not learning it one way and one
way only then forcing that pattern upon the problem when another
solution/pattern might be a better fit.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top