Skip to content

0035: Composite Pattern in CollectionManager

01/06/2011

Hi,

In the last entry I mentioned that I’d managed to implement CollectionManager. This is a additional module that for now allows only browsing through the collections, but
in the future I will try to enhance it to full manager that will allow browsing, deleting, merging, copying and moving elements on different abstraction levels. What does it mean?

Let me explain:

Data structure in OLGAtherer consists of folder that consists of databases that consist of repositories that consist of entities 🙂 As you can see, there is at least four
levels that I call “abstraction level”. In the inner application structures, all four levels are represent by classes/objects: DBContainer (folder(s)), DB (databases), EntityCollection
and IEntity interface that is implemented by any collection collection item (Book, Comic, Wine, etc.).

All of them differ in any detail, but we want to treat them in one, consistent way. And here comes the Composite pattern 🙂 What is it?

I don’t want to provide detail description of whole pattern, because English isn’t my native language – here we can read about it: http://www.dofactory.com/Patterns/PatternComposite.aspx 🙂

In short, we can create common interface that will be implemented by all classes in the structure tree (three classes and one interface mentioned above). I’d like to show you how I did it.

In the beginning, I thought about actions that composite may take. As I said, I’d like it to be copied, moved, deleted, listed and so on – so I created interface IManagedComposite that contained method
signatures such as DeleteChild(IManagedComposite child),…, List GetChildren() and property bool HasChildren.

When I tried to implement it, I found it quite difficult and painful, due to lack of detailed plan – how the manager has to be like. This issue (tough implementation process) is widely described
in books about Objective Programming. They states that programmer shouldn’t write excessive code for the future, possible use, but rather write less code that is needed right now.
This was my situation – I started to think about it once again and figured out that I need only methods that will allow user to list the composites in one, consistent way.
Now the job started to be easy and fun. Look at the interface:

public interface IManagedComposite
{
    Dictionary GetChildren();
    string Name { get; }
    bool HasChildren { get; }
}

This is sensible – we want composite item to identify itself by giving name, and to provide us with its children. Name is sufficient to find the composite at the certain level, so
we will be able to find the desired object and change it in the future (when new actions will be needed). So, next I had to implement interface in 3 classes. Property HasChildren
is trivial ({return this.children.Count != 0;}), but I will show you an implementation of the other members in different classes:

DBContainer class that represents folder containing database files:

public Dictionary GetChildren()
{
    //collect children only if the dictionary is empty. This is a performance fix.
    if (this.children.Count == 0)
       foreach (string fileName in Directory.GetFiles(this.folderPath))  //go through all db files in the directory and collect their names
       {
          IManagedComposite db = new DB(fileName);
          if ((db as DB).IsValidDb)
             this.children.Add(db.Name, db);
       }

    return this.children;
}

public string Name
{
    get { return Path.GetDirectoryName(this.folderPath); } //returns directory name
}

DB class that represents one database:

public Dictionary GetChildren()
{
    if (this.children.Count == 0)
       foreach (CollectionData value in GetCollectionDataCollection().Read()) //go through all collections in database
       {
           this.children.Add(value.FriendlyCollectionName, GetBookCollection(value.IdNo));
       }

    return this.children;
}

public string Name
{
    get { return this.name; } //returns DB name
}

EntityCollection:

public Dictionary GetChildren()
{
   if (this.children.Count == 0)
      foreach (T item in this.items)  //go through all entities in the collection
         this.children.Add(item.ToString(), item);

   return this.children;
}

public string Name
{
    get { return this.friendlyName; }  //this is potential issue
}

And IEntity that inherits from IManagedComposite now, so for example, class Book : IEntity implements IManagedComposite in the same time:

public Dictionary GetChildren()
{
    return null; //no children
}

public string Name
{
    get { return this.ToString(); } //overriden ToString() method.
}

As you can see, every one class implements the GetChildren() method in different way. From listing files, through reading from inside of DB, to return null in case of leaves (entities have no children).
One can see in the code above at least one potential issue – returning friendlyName by EntityCollection can cause problems, because this name isn’t unique at the Collection level. But I see this
possibility and will try to fix it.
Anyway, how can we now list all of the composites? Very easy:

I needed to create form with two ListBoxes – lbxLeft and lbxRight. I’ve created CustomControl called CompositeListBox that aggregates ListBox and Stack that stores currently processed
composite. Then, only one method is actually relevant:

private void DisplayCompositesOnList()
{
	//Get children from currentComposite (displayedComposite field)
   Dictionary displayedCompositeGetChildren = this.displayedComposite.GetChildren();
   if (displayedCompositeGetChildren == null)
      return;

	//Clear items from listbox
   this.lbxMain.Items.Clear();
   //Add ... in the first line
   this.lbxMain.Items.Add(Return_Symbol);
   //Fill rest of the lines with childrens' names
   foreach (KeyValuePair displayedComposite in displayedCompositeGetChildren)
      this.lbxMain.Items.Add(displayedComposite.Key);
}

When we want to go deeper into the structure, just doubleclick on desired component. Then selected item becomes currentComposite, and is being put on the stack.
When we want to go back, just pop item from the stack… Nice and easy 🙂

In the future, any changes would be easy due to this approach – it’s another time when design patterns appeared to be very handy and worth to use. Composite pattern
handles the issue with easiness and lets me modify all different components in common way, so I think that implementing copy/move functionality will require adding two
methods to the interface, and implementing them in the classes. Objective architecture of the Model library assures that this won’t take too long time and effort. Hopefully.
🙂

I know that this entry may be quite difficult to read, but I hope that you’ve made it and you found this article helpful in any way…
Best regards
Paweł

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: