Arlo Belshee on 8 Jul 2003 16:03:01 -0000


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [ALACPP] chapter 8


> I would never use the factory template in my code. It is a degenerate
> abstraction over a map template. I would always just use a map
> directly. I am calling it degenerate because it does not add any
> additional functionality or abstract away any of the details of a map. All
> it does is rename the interface methods: map::insert becomes
> Factory::Register, map::erase become Factory::Unregister, and map::find
> becomes Factory::CreateObject. What's the point?

In and of itself, not much.

However, it provides a good base to which you can easily attach some very
useful functionality.

For example, I typically add a nested class that can be used for
autoregistration: each factory-constructable class automatically registers
itself with the correct factory at static initialization time. This means that
there is no central location containing a list of all the classes that 1) has
to be kept up to date, and 2) has a physical dependency on everything.

Also, I pull CreateObject into a policy. The most common implementation of the
policy is PrototypePolicy, which clones (deep copy) a registered instance to
make a new class. However, I also often create NewPolicy, which provides a set
of overrides for CreateObject that accept constructor args. If I'm using
non-default heaps, factory is extremely useful for controlling what objects
get created on what heaps, without burying that information in a hundred
places throughout the code base.

Finally, I have CreateObject always return a smart pointer, rather than a
basic pointer. The factory provides a type computer that gives the pointer
type for any type that it can construct. That way, no object ever appears in
the real system (even for a short while) as a basic pointer. Then, if I need
to change anything about its memory management (garbage collection, etc), I
just change it in one place: the type computer. Everyone else uses that type
computer when determining how to store the ponter, so they are all
automagically updated if I change my memory model.

(Note: if the factory becomes a central part of the system, I usually refactor
the type computer out into a traits implementation. That way, the factory and
everyone else can depend on the traits class, and nothing has to depend on the
factory unless it actually creates objects. However, this adds complexity to
the system, so I only do it once "several" unrelated things are depending on
factory, just to get the pointer type.)

Basically, Factory is a useful abstraction of your memory model(s). You can
put all the design decisions about memory management into one place, and then
all of the rest of your code is immune to changes in your memory managment
policies. If you suddenly note that performace blows and you want to use a
pooled allocation system to improve locality of reference, you write one new
policy, change the typedef for the active factory, and poof. Everything else
adapts.

Arlo


_______________________________________________
alacpp mailing list
alacpp@xxxxxxxxxxx
http://lists.ellipsis.cx/mailman/listinfo/alacpp