Jump to content

Feedback on factory pattern


Recommended Posts

Hi!

 

A few weeks ago, I had the opportunity to use the factory pattern, something I wanted to do ever since I heard about it. I would like to know if I did it right, and what I could have done differently. ;-)

 

I wanted to build an abstract class that I could use with multiple scientific CCD cameras. This class has 5 VIs:

- Initialize

- Snap

- Sequence

- Close

- GetTemperature

 

The main question I have is that every camera that inherits this abstract class had a different way of being initialized. For example, CameraA had a controllable temperature setting and CameraB did not, so when implementing the Initialize VI, CameraA will need a target temperature input, while CameraB won't.

For each camera, I created a "initializing options" cluster, and I passed this cluster to the Initialize VI through a variant. For CameraA this cluster had a "target temperature" numeric among other things, while CameraB did not. The specific implementation for each camera uses the "Variant to Data" function to retrieve the cluster values.

It works, but I am wondering if this is a good way of doing it. While I was researching how to pass specific data using the factory framework, I could not find a "this-is-the-one-and-only-method-you-should-use" answer. Are there potential problems with using a variant that I did not think about? Is there another way of passing clusters that will be different for every child using the factory pattern?

 

Other than this specific question, is there a major drawback to using the factory pattern?

 

Thanks!

Link to comment

The factory pattern is great and I like to use it all over the place. I think your approach is good, and the variant method definitely works, I've seen it many times before. However it requires you to be extra diligent since a slight difference between what was passed inside the variant and the way to cast it back into usable data would generate an error that could be tough to troubleshoot along the road. Unless you use a typedef, modifying the data type on one side won't automatically modify the other side.

 

One alternative idea would be that the initialization data is itself an object. You could have an abstract class "initialization data", and then child classes such as "InitDataClassA" and "InitDataClassB". Look at the decorator pattern, it might give you some idea. Of course you're adding another layer of LVOOP, so there is a complexity trade-off.

Link to comment

There's no one right way of doing this, it depends on your factory. Your approach with a variant seems reasonable. If you're reading the settings from a file, you might consider using a JSON or XML string instead (an INI file section also works). That way you could read the class name from the string, instantiate the appropriate class, and pass the entire string to a VI in that class to parse. This also makes the settings easier to edit by hand if necessary, and provides some ability for the VI to recover from incomplete settings information. It sounds like it's unnecessary in your application, but in some cases your factory classes might implement a VI that prompts the user to enter the appropriate settings for that specific class.

Link to comment

Something else I would throw in:

If you have an object with a reference in it of any kind, I think it really pays off to have a explicit "allocate" or "connect" or whatever function which converts your object from a "dead" object (ie its just a cluster) to a "living" one, whose state has to be carefully managed. I would also recommend it be different from your "construct" function.

 

A specific pattern I've found to be successful is similar to what manudelavega suggested. You have a "configuration" class and an execution class. You can drop down your config class, change the settings that make sense, and then initialize your runtime class using that configuration class. If you want to get fancy you can load into that configuration class handy things like saving to disk or specifying what specific runtime class it needs to be loaded into, and so from your user's perspective theres really just the one class that happens to metamorphose through its life cycle.

Edited by smithd
Link to comment

A slight modification of the variant approach: Pass the common camera parameters as a cluster and pass only the device specific parameters by variant. This variant could either be a separate parameter or a member of the initialization cluster.

Edited by candidus
Link to comment

Thank you all for the very informative answers!

 

drjdpowell : thanks for making me aware of the JSON library, especially since we use JSON in another project (in C though), this is going to be very helpful in the next few months I believe.

 

Thanks manudelavega and smithd for suggesting separating the configuration from the initialization. I looked at the decorator pattern, but I might have to read this multiple times before I am ready to try it ;-)

I usually mostly do hardware stuff, so as long as classes correspond to physical objects I am not too lost. I think I will try that approach on my next small project, and I will also add a VI that prompts the user to enter the appropriate settings like ned suggested.

 

A question to smithd : what do you mean by "actively managing" the state of the object if it has a reference?

 

Thanks!

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.