How to design constructors in a hierarchy where there are just readonly fields without having too many parameters?
I have designed a hierarchy, every class has 2 readonly properties mapped to 2 private fields.
Every class has a cosntructor that inherits the parent class one.
The problem is that at every level of hierarchy the number of parameters increase of 2:
TBaseClass.Create (par1, par2);
TSubClass.Create(par1, par2, par3, par4);
TSubSubClass.Create(par1, par2, par3, par4, par5, par6);
[...]
Is it ok to have constructors with 6-8 parameteres? After creation my objects should be immutable, so this is why I try to initialize all f开发者_开发问答ileds in the constructors.
Is there another technique you can suggest or should I go with the above mentioned approach? Thanks.
As long as they're well-documented, I've never had any stigma against functions with large numbers of parameters. So an 8-param constructor wouldn't scare me.
However, I can see where the explosion-of-params could occur here, especially if you start adding more than 2 properties per object. I could also see an uncomfortable proliferation of constructor overloads, if some of those params can be defaulted/optional.
With that in mind, you might want to encapsulate the complexities of setting all those params, by using a construction pattern. Builder comes to mind, though Factory or Prototype might also be useful.
Best to stick with conventions when you can. A Builder implies a sequential or multiple object creation process. Abstract Factory is more appropriate for creating a single object from a hierarchy.
Having said that, the regularity does seem a little odd. Does SubClass3 in fact need all 6 properties or only it's two? Remember LSP - SubClass3 is supposed to be completely substitutible for BaseClass so at each level the new ancestor assumes responsibility for the entire set, which is usually more than just passing them back through constructors.
Why don't you let those properties be writable and protect the object by casting it to an interface? Like this:
type
IMyObject = interface
function GetProperty1(): integer;
function GetProperty2(): boolean;
end;
TMyObject = class(TInterfacedObject, IMyObject)
public
constructor Create();
function GetProperty1(): integer;
function GetProperty2(): boolean;
procedure SetProperty1(Value: integer);
procedure SetProperty2(Value: boolean);
end;
function CreateMyObject: IMyObject;
var obj: TMyObject
begin
obj := TMyObject.Create;
obj.SetProperty1(45);
obj.SetProperty2(false);
Result := obj;
end;
精彩评论