mike55 Posted March 6, 2007 Posted March 6, 2007 Hi all I have being looking through the book "Design Patterns" by the Gang of Four, I came across the composite pattern and implemented a sample app the demonstrates the pattern working (hopefully I did it correctly). After some further reading using the web other resources, I came across a statement that said that a child in the pattern could have multiple parents. I have being trying to figure out how to adjust my sample app to accomidate this; I considered adding an list to the child, which allowed it to store a reference to all its parents, and the same for the parent, so that it could store all its children. I am not sure if this is the best approach, can anyone suggest any alternative? Here is the code that I am using in my basic composite pattern: The Abstract child using System; using System.Collections.Generic; using System.Text; namespace CompositePattern { abstract class AbstractChild : CompositePattern.IAbstractChild { protected string name; public AbstractChild(string name) { this.name = name; } public abstract void Add(AbstractChild soldier); public abstract void Remove(AbstractChild soldier); public abstract void Display(int indent); } } The Child using System; using System.Collections.Generic; using System.Text; namespace CompositePattern { class Child: AbstractChild { public Child(string name):base(name) { } public override void Add(AbstractChild soldier) { Console.WriteLine("Cannot add to a child."); //(throw new Exception("The method or operation is not implemented."); } public override void Remove(AbstractChild soldier) { Console.WriteLine("Cannot remove from a child."); //throw new Exception("The method or operation is not implemented."); } public override void Display(int indent) { Console.WriteLine(new string('-', indent) + " " + name); //throw new Exception("The method or operation is not implemented."); } } } The parent using System; using System.Collections.Generic; using System.Text; namespace CompositePattern { class Parent: AbstractChild { //private ArrayList elements = new ArrayList(); private List<AbstractChild> elements = new List<AbstractChild>(); public Parent(string name): base(name) { } public override void Add(AbstractChild soldier) { elements.Add(soldier); //throw new Exception("The method or operation is not implemented."); } public override void Remove(AbstractChild soldier) { elements.Remove(soldier); //throw new Exception("The method or operation is not implemented."); } public override void Display(int indent) { Console.WriteLine(new string('-', indent) + " + " + name); foreach (AbstractChild aSoldier in elements) { aSoldier.Display(indent + 2); } //throw new Exception("The method or operation is not implemented."); } } } And finally the main using System; using System.Collections.Generic; using System.Text; using System.Data; namespace CompositePattern { class MainApp { public static void Main() { Parent myParent = new Parent("John Doe"); myParent.Add(new Child("Tom")); myParent.Add(new Child("Dick")); myParent.Add(new Child("Harry")); myParent.Display(0); Console.Read(); } } } Mike55. Quote A Client refers to the person who incurs the development cost. A Customer refers to the person that pays to use the product. ------ My software never has bugs. It just develops random features. (Mosabama vbforums.com)
mike55 Posted March 6, 2007 Author Posted March 6, 2007 Is the flyweight pattern the way to go with this problem? I am after reading in http://www.research.ibm.com/designpatterns/pubs/ph-jun98.pdf in the last paragraph on page 4, that the composite pattern can generate a lot of overhead if you are applying it to too fine a granularity. The flyweight is appliciable if there is a lot of redundancy. Any suggestions? or am I going completely off track. Mike55 Quote A Client refers to the person who incurs the development cost. A Customer refers to the person that pays to use the product. ------ My software never has bugs. It just develops random features. (Mosabama vbforums.com)
mike55 Posted March 10, 2007 Author Posted March 10, 2007 Here is what I have finished up with, I would appreciate it if anyone could let me know if I have done it correctly, or if I have completely mis-read the documentation. The Component Class. using System; using System.Collections.Generic; using System.Text; namespace CompositePattern { abstract class AbstractEmployee : CompositePattern.IAbstractEmployee { public string name; public string title; public decimal salary; //This is a list of references for all my parents. See GoF pg166(Implementation pt1.) for reasoning. public List<AbstractEmployee> myParents = new List<AbstractEmployee>(); public AbstractEmployee(string name, string title, decimal salary) { this.name = name; this.title = title; this.salary = salary; } //Add a leaf to a parent, or add a parent to another parent. public abstract void Add(AbstractEmployee employee); //Remove a leaf from a parent. public abstract void Remove(AbstractEmployee employee); //Display all the leaves for a particular parent. public abstract void Display(int indent); //Get the name of the parent/leaf. public abstract string GetName(); //Get the salary of the parent/leaf. public abstract string GetTitle(); //Get the salary of the parent/leaf. public abstract decimal GetSalary(); //Add a new reference to the object for a new parent. public abstract void AddParentReference(AbstractEmployee myParentRef); //List all the references to parents that an object has. public abstract void ListParentReference(); public abstract void RemoveReferences(CompositeElement myParentRef); } } The Composite Class using System; using System.Collections.Generic; using System.Text; namespace CompositePattern { class CompositeElement: AbstractEmployee { List<AbstractEmployee> myElements = new List<AbstractEmployee>(); public CompositeElement(string name, string title, decimal salary): base(name, title, salary) { } //Add an employee to the manger. public override void Add(AbstractEmployee myEmployee) { myElements.Add(myEmployee); } //Remove an employee from the manger. public override void Remove(AbstractEmployee myEmployee) { myElements.Remove(myEmployee); } //1. Begin by printing the name of the parent, 2. followed by its children. public override void Display(int indent) { //1. Print the name of the parnet. Console.WriteLine(new string('-', indent) + "+ " + name); //2. Print all the children of the parent. foreach (AbstractEmployee myEmployee in myElements) { myEmployee.Display(indent + 1); } } //Return the name of a parent. public override string GetName() { return name; } //Return the title of the parent. public override string GetTitle() { return title; } //Return the salary of the parent. public override decimal GetSalary() { return salary; } //Add a reference to the parent. public override void AddParentReference(AbstractEmployee myParentRef) { myParents.Add(myParentRef); } //List all the references that the parent has to other parents. public override void ListParentReference() { if (myParents.Count == 0) { Console.WriteLine("No references exist."); } else { //1. Print the name of the parnet. Console.WriteLine(new string('-', 1) + "+ " + name); int counter = 0; //Print all the references that the object has to parents. foreach (AbstractEmployee myRef in myParents) { counter += 1; Console.WriteLine("Reference " + counter + ": " + myRef.GetName()); } } } //Remove a reference to a parent. public override void RemoveReferences(CompositeElement myParentRef) { myParents.Remove(myParentRef); } } } The Leaf Class using System; using System.Collections.Generic; using System.Text; namespace CompositePattern { class Employee: AbstractEmployee { public Employee(string name, string title, decimal salary):base(name, title, salary) { } public override void Add(AbstractEmployee myEmployee) { Console.WriteLine("Cannot ADD to an employee, operation can only be performed on an manager."); } public override void Remove(AbstractEmployee myEmployee) { Console.WriteLine("Cannot REMOVE from an employee, operation can only be performed on an manager."); } //Display the employee. public override void Display(int indent) { Console.WriteLine(new string('-', indent) + " " + name); } //Get the name of the employee. public override string GetName() { return name; } //Get the title of the employee. public override string GetTitle() { return title; } //Get the salary of the employee. public override decimal GetSalary() { return salary; } //Add a reference to the child. public override void AddParentReference(AbstractEmployee myParentRef) { //Console.WriteLine("Cannot ADD_PARENT_REFERENCE from an employee, operation can only be performed on an manager."); myParents.Add(myParentRef); } //List all the references that the child has to other parents. public override void ListParentReference() { if (myParents.Count == 0) { Console.WriteLine("No references exist."); } else { //1. Print the name of the parnet. Console.WriteLine(new string('-', 1) + "+ " + name); int counter = 0; //Print all the references that the object has to parents. foreach (AbstractEmployee myRef in myParents) { counter += 1; Console.WriteLine("Reference " + counter + ": " + myRef.GetName()); } } } //Remove a reference to a parent. public override void RemoveReferences(CompositeElement myParentRef) { myParents.Remove(myParentRef); } } } And finally, the code from my Main class //1. Create the primary parent. CompositeElement root = new CompositeElement("PJimmy", "Managing Director", 100000); CompositeElement comp = new CompositeElement("PMichael", "Developer", 17000); //2. Create an employee and add a reference. Employee emp = new Employee("Tom", "Quality Manager", 50000); emp.AddParentReference(root); emp.AddParentReference(comp); comp.AddParentReference(root); //Display the references. emp.ListParentReference(); Mike55. Quote A Client refers to the person who incurs the development cost. A Customer refers to the person that pays to use the product. ------ My software never has bugs. It just develops random features. (Mosabama vbforums.com)
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.