Composite Pattern Simplified
What do I lose by not implementing the Component and treating everything as a Composite?
I have given up the implementation for Leaf node:
I.e.
class Component : IComponent
{
/*...*/
}
Now plz take a look at my code.
public interface IComponent
{
int ID { get;set; }
string Name { get;set;}
void Add(IComponent item);
void Remove(IComponent item);
List<IComponent> Items { get; }
void Show();
}
public class Composite : IComponent
{
private int _id;
public int ID
{
get { return _id; }
set { _id = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public Composite(int id, string name)
{
_id = id;
_name = name;
}
private List<IComponent> _items = new List<IComponent>();
public void Add(IComponent item)
{
_items.Add(item);
}
public vo开发者_运维知识库id Remove(IComponent item)
{
_items.Remove(item);
}
public List<IComponent> Items
{
get
{
return new List<IComponent>(_items);
}
}
public void Show()
{
Console.WriteLine("ID=" + _id + "; Name=" + _name);
}
}
class Program
{
static void Main(string[] args)
{
IComponent root = new Composite(1, "World");
IComponent asia = new Composite(2, "Asia");
IComponent europe = new Composite(3, "Europe");
root.Add(asia);
root.Add(europe);
asia.Add(new Composite(4, "China"));
asia.Add(new Composite(5, "Japan"));
europe.Add(new Composite(6, "Germany"));
europe.Add(new Composite(7, "Russia"));
root.Show();
Program.Traverse(root.Items);
Console.ReadLine();
}
static void Traverse(List<IComponent> items)
{
foreach (IComponent c in items)
{
c.Show();
Traverse(c.Items);
}
}
}
What is wrong with this approach of Composite Pattern? What kind of problem can I face with this type of design?
You're giving up any chance to subclass the "Leaf", if it turns out you have different types of "nodes" you'll probably end up polluting the structure in one way or another. And you're violating the single responsipbility priciple too. It is very easy to get pollution of all sorts with the composite pattern, and I think it always pays off to do it cleanly.
If I understand correctly, there is not a concept of leaf node, in composite pattern.
Any node which doesn't have a child is automatically a leaf node.
Looking at your code, this is not needed
private List<IComponent> _items = new List<IComponent>();
public void Add(IComponent item)
{
_items.Add(item);
}
public void Remove(IComponent item)
{
_items.Remove(item);
}
public List<IComponent> Items
{
get
{
return new List<IComponent>(_items);
}
}
I am looking at ControlCollection
class, which is a property of Control
class.
Though not exactly composite pattern, every Control knows of who it is child of, which is missing from your code.
My understanding could be totally off. Experts can correct me :)
EDIT: I looked at the dofactory reference, which seems to have a concept of leaf class in composite pattern. My mistake of totally not understanding it.
But I would suggest you look at the way .net implements kind of composite pattern by having Control
, ControlCollection
& related classes.
EDIT2: If the code above is to be removed, you will have another class which is a collection of IComponent
which you can expose by using a property IList<IComponent>
, which in turn will have methods to add
/remove
.
EDIT3: .net doesn't restrict the user from adding child controls in the above class hierarchy. You could use the dofactory way of design, if you want to restrict the ability for someone to define a leaf node (one that doesn't have any child node).
EDIT4: The way dofactory code shows, you will have to define a leaf node, which will throw NotImplementedException
for Add
/`Remove'.
精彩评论