I have a class that requires a large number of properties for initialization:
H开发者_JS百科and hand = new Hand();
hand->skinColor(Color(0.5, 0.5, 0.2));
hand->indexFingerLength(0.5);
hand->middleFingerLength(0.6);
hand->ringFingerLength(0.55);
...
hand->init(); // Builds the hand model
These properties are only valid to modify up until the call to init(), which uses them to build the class. The problem is that these properties can still be modified after the call to init() to no effect, an interface which could mislead the user to think that they will have an effect.
Is there a better way to refactor this other than moving all the properties into an argument list for init()?
struct structHandParms
{
param1;
param2;
param3;
...
};
structHandParms stParams;
Hand hand = new Hand(stParams)
You could add a "Hand_Init" struct that was passed to the constructor:
Hand_Init hand_init;
hand_init.skinColor = Color(0.5, 0.5, 0.2);
hand_init.indexFingerLength = 0.5;
hand_init.middleFingerLength = 0.6;
hand_init.ringFingerLength = 0.55;
Hand hand = new Hand(hand_init);
That way as soon as the constructor call completes, the hand is initialized, and you don't have a bunch of anonymous arguments that could cause confusion.
If you're going to create more than one Hand
, then maybe use something like the Builder Pattern.
// set properties
HandBuilder hb;
hb.skinColor(Color(0.5, 0.5, 0.2));
hb.indexFingerLength(0.5);
hb.middleFingerLength(0.6);
hb.ringFingerLength(0.55);
// create object
Hand hand = hb.buildHand();
This totally screams to have the logic in the constructor instead of separate methods followed by init. Then it's completely obvious (and enforced by the compiler) that they can't be changed later. If there are a lot of parameters, group them all into a struct which is populated and passed into the constructor instead of 25 separate parameters.
"the call to init(), which uses them to build the class" really builds a class or does it initialise the instance of this class?
Why don't you do your whole initialisation in the ctor and pass the required values as parameters?
I think this is a good reason to maintain a documentation and user manual for your project or maybe you can change to send a descriptor to your class. Then, you create the descriptor, fill it with the configuration and sends all the information at once to the constructor.
You could solve the problem of post init() modification by throwing an exception. This would prevent a user from making a call to one of the setting functions and expecting it to do something.
As an alternative, you could create a HandParameter class/struct. This object would be responsible for gathering all the data you need to have about the Hand object. Next, you could make your Hand object's init() function take a HandParameter as its only argument.
struct HandParam
{
// Whatever settings you need
};
class Hand
{
bool initialized;
// other private data
public:
Hand();
Hand( const HandParam& params ); // Calls the init() funciton with params
void init( const HandParam& params ); // sets up hand and sets initialized to true
// Whatever else you need in your class
};
Good Luck!
精彩评论