Object-oriented – Avoiding constructors with many arguments

architectural-patternscdesign-patternsfactory-methodobject-oriented

So I have a factory which creates objects of different classes.
The possible classes are all derived from an abstract ancestor.
The factory has a configuration file (JSON syntax) and decides which class to create, depending on the user's configuration.

To achieve this, the factory uses boost::property_tree for JSON-parsing.
He walks through the ptree and decides which concrete object to create.

However, the product-objects have many fields (attributes).
Depending on the concrete class, the object has about 5-10 attributes, in the future maybe even more.

So I'm not sure how the constructor of the objects should look like.
I can think of two solutions:

1) The product's constructor expects every attribute as a parameter, thus, the constructor will end up with 10+ parameters. This will be ugly and lead to long, unreadable code lines. However, advantage is that the factory can parse the JSON and invoke the constructor with the correct parameters. The product class does not need to know that it has been created due to JSON configuration. It does not need to know there is JSON or configuration involved at all.

2) The product's constructor only expects one argument, the property_tree object. Then it can parse the needed information. If am information in the config is missing or out-of-bounds, each product class can react properly.
The factory does not need to know what arguments are needed by the several products. The factory also does not need to know how to react in case of wrong configuration. And the constructor interface is unified and small.
But, as a disadvantage, the product needs to extract the needed information from the JSON, thus, it knows how it is constructed.

I tend to prefer solution 2).
However, I'm not sure if this is good factory pattern.
It feels somehow wrong letting the product know that it is created with JSON configuration.
On the other side, new products can be introduced very simple.

Any opinions on that?

Best Answer

I wouldn't do option 2, because then you have forever convolved your object's construction with boost property tree parsing. If you're comfortable with a class that needs that many parameters, you should be comfortable with a constructor that needs that many parameters, such is life!

If your main concern is code readability, you can use the builder pattern, it's basically the c++/java stopgap for lack of named arguments. You end up with things that look like this:

MyObject o = MyObject::Builder()
               .setParam1(val1)
               .setParam2(val2)
               .setParam3(val3)
             .build();

So now MyObject will have a private constructor, that gets called in Builder::build. The nice thing is that that will be the only place you ever have to call a constructor with 10 parameters. The boost property tree factory will use the builder, and subsequently if you want to construct a MyObject directly or from a different source, you would go through the builder. And the builder basically lets you clearly name each parameter as you pass it in, so it's more readable. This obviously adds some boilerplate, so you'll have to decide if it's worth it compared to just calling the messy constructor, or lumping together some of your existing parameters into structs, etc. Just throwing another option on the table.

https://en.wikipedia.org/wiki/Builder_pattern#C.2B.2B_Example