azhew Posted January 27, 2016 Report Share Posted January 27, 2016 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! Quote Link to comment
eberaud Posted February 1, 2016 Report Share Posted February 1, 2016 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. Quote Link to comment
ned Posted February 2, 2016 Report Share Posted February 2, 2016 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. Quote Link to comment
smithd Posted February 3, 2016 Report Share Posted February 3, 2016 (edited) 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 February 3, 2016 by smithd Quote Link to comment
drjdpowell Posted February 3, 2016 Report Share Posted February 3, 2016 I use the JSON library in the LAVA CR to hold configuration information. This is often just converted to/from a cluster internally, but the conversion is more tolerant of changes than a straight variant-to-cluster conversation. Quote Link to comment
candidus Posted February 6, 2016 Report Share Posted February 6, 2016 (edited) 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 February 6, 2016 by candidus Quote Link to comment
azhew Posted February 8, 2016 Author Report Share Posted February 8, 2016 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! Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.