I\'m regularly facing following pattern: public abstract class BaseItem { BaseIt
ID: 644460 • Letter: I
Question
I'm regularly facing following pattern:
public abstract class BaseItem
{
BaseItem[] children;
// ...
public void DoSomethingWithStuff()
{
StuffCollection collection = new StuffCollection();
foreach(child c : children) c.AddRequiredStuff(collection);
// do something with the collection ...
}
public abstract void AddRequiredStuff(StuffCollection collection);
}
public class ConcreteItem : BaseItem
{
// ...
public override void AddRequiredStuff(StuffCollection collection)
{
Stuff stuff;
// ...
collection.Add(stuff);
}
}
Where I would prefer something like this, for better information hiding:
public abstract class BaseItem
{
BaseItem[] children;
// ...
public void DoSomethingWithStuff()
{
StuffCollection collection = new StuffCollection();
foreach(child c : children) collection.AddRange(c.RequiredStuff());
// do something with the collection ...
}
public abstract StuffCollection RequiredStuff();
}
public class ConcreteItem : BaseItem
{
// ...
public override StuffCollection RequiredStuff()
{
StuffCollection stuffCollection;
Stuff stuff;
// ...
stuffCollection.Add(stuff);
return stuffCollection;
}
}
What are pros and cons of each solution?
For me, giving the implementation access to parent's information is some how disconcerting. On the other hand, initializing a new list, just to collect the items is a useless overhead ...
What is the better design? How would it change, if DoSomethingWithStuff wouldn't be part of BaseItem but a third class?
PS: there might be missing semicolons, or typos; sorry for that! The above code is not meant to be executed, but just for illustration.
Explanation / Answer
initializing a new list, just to collect the items is a useless overhead
instantiate 2 class-level collections, once. The first is for the cumulative AddStuff() and the other is to pass to the child - and is reused.
public abstract class BaseItem
{
BaseItem[] children;
StuffCollection masterCollection;
StuffCollection transferCollection;
// ...
public void DoSomethingWithStuff()
{
masterCollection = masterCollection?? new StuffCollection();
transferCollection = transferCollection?? new StuffCollection();
transferCollection.Clear();
foreach(child c : children) {
c.RequiredStuff(transferCollection);
masterCollection.AddRange(transferCollection);
transferCollection.Clear();
}
// do something with the collection ...
}
public abstract void RequiredStuff(StuffCollection aTransferCollection);
}
public class ConcreteItem : BaseItem
{
// ...
public override void RequiredStuff(StuffCollection collector )
{
Stuff stuff;
// ...
collector.Add(stuff);
}
}