Home > .NET/C#, Software > Applying the Adapter Pattern to the Composite Pattern Best Practice

Applying the Adapter Pattern to the Composite Pattern Best Practice

I’ve recently stumbled on a seemingly simple issue. If you have a Composite pattern, how do you create an Adapter pattern for it? In other words, if we want to create a wrapper for a set of classes in a composite, how do you map this while hiding the composite classes themselves?

Here’s a concrete example of this. Let’s say you have the following model:

    public abstract class TreeItem
    {

    }

    public class Branch : TreeItem
    {
        private readonly List<TreeItem> _children = new List<TreeItem>();

        public void Add(TreeItem a)
        {
            _children.Add(a);
        }
    }

    public class Leaf : TreeItem
    {

    }

Now, you need to adapt it. For the sake of simplicity, here’s a partial implementation:

    public abstract class TreeItemAdapter
    {
    }

    public class BranchAdapter : TreeItemAdapter
    {
        private readonly Branch _branch;
        private readonly List<TreeItemAdapter> _children = new List<TreeItemAdapter>();

        public  BranchAdapter(Branch branch)
        {
            _branch = branch;
        }

        public void Add(TreeItemAdapter itemAdapter)
        {
            // Here, we want to do _branch.Add(itemAdapter._value) or something similar
            // but we can't, since protected values in TreeItemAdapter will not be accessible
            _children.Add(itemAdapter);
        }
    }

    public class LeafAdapter : TreeItemAdapter
    {
        private readonly Leaf _leaf;

        public LeafAdapter(Leaf leaf)
        {
            _leaf = leaf;
        }
    }

Let’s say the goal is to be able to write this code;

Branch branch = new Branch();
Leaf leaf = new Leaf();

BranchAdapter branchAdapter = new BranchAdapter(branch);
LeafAdapter leafAdapter = new LeafAdapter(leaf);

branchAdapter.Add(leafAdapter);

You can try it if you want, the puzzle is simple, but not obvious! You need to access the Leaf object in LeafAdapter to be able to add it to the contained Branch object, but you can’t! One solution is to move the contained object in a private variable in TreeItemAdapter, which I think is a step back in elegance for the sake of functionality, but then you still cannot access the value because BranchAdapter is not the same time than TreeItemAdapter, therefore you can’t access its protected values! You could make a public accessor to get the adapted object, but then again, the goal here is to hide this object and avoid other classes working on it directly.

So, did you find it? Here’s my solution.

    public abstract class TreeItemAdapter
    {
        protected TreeItem GetModelOf(TreeItemAdapter itemAdapter)
        {
            return itemAdapter.GetModel();
        }

        protected abstract TreeItem GetModel();
    }

    public class BranchAdapter : TreeItemAdapter
    {
        private readonly Branch _branch;
        private readonly List<TreeItemAdapter> _children = new List<TreeItemAdapter>();

        public  BranchAdapter(Branch branch)
        {
            _branch = branch;
        }

        public void Add(TreeItemAdapter itemAdapter)
        {
            _branch.Add(GetModelOf(itemAdapter));
            _children.Add(itemAdapter);
        }

        protected override TreeItem GetModel()
        {
            return _branch;
        }
    }

    public class LeafAdapter : TreeItemAdapter
    {
        private readonly Leaf _leaf;

        public LeafAdapter(Leaf leaf)
        {
            _leaf = leaf;
        }

        protected override TreeItem GetModel()
        {
            return _leaf;
        }
    }

It’s a little bit of a mind twister, but it’s not complex; as a BranchAdapter instance, you can access protected functions of other BranchAdapter instances, but not TreeItemAdapter instances. However, you do have access to your own protected functions of TreeItemAdapter through inheritance. Therefore, you can ask, or defer, the responsibility to deal with other TreeItemAdapter instances to TreeItemAdapter itself! It can then, again using inheritance, allow each Adapter implementations to deal with their values, access their protected values and return the result without ever creating non-protected accessors.

The issue was introduced while trying to create a ViewModel wrapping the Model in a MVVM implementation in WPF. I tried finding a best practice for this specific situation, which seemed like something that could happen often, but I found nothing. I hope this will be useful to someone, and if you have other implementations for this problem you’d like to share or if this was useful to you, please leave some feedback!

Categories: .NET/C#, Software
  1. No comments yet.
  1. No trackbacks yet.

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 )

Connecting to %s

%d bloggers like this: