150 likes | 161 Views
Learn to structure classes using Composite Design Pattern to manage employee salaries and hierarchy. Includes Boss and Employee classes with methods for adding, removing, and retrieving subordinates, implementing a tree-like structure. AWT/Swing widgets used to visualize employee tree. Abstract class defines common functionality. Understand when to use NoSuchElementException. Interesting problem-solving approach demonstrated.
E N D
The Composite Design Pattern • The AWT/Swing widgets form a tree-like structure • The Composite Design Pattern is well suited for such a structure
A Hierarchy in a Company • This is clearly a tree structure where the “bosses” are internal nodes and the leaves are the workers • An interesting problem to solve is how to structure the classes such that you can find the total salaries for an employee and all subordinate employees (if any)
The Abstract Employee public abstract class AbstractEmployee { protected String name; protected long salary; protected Employee parent = null; protected boolean leaf = true; public abstract long getSalary(); public abstract String getName(); public abstract boolean add(Employee e) throws NoSuchElementException; public abstract void remove(Employee e) throws NoSuchElementException; public abstract Enumeration subordinates(); public abstract Employee getChild(String s); public abstract long getSalaries(); public boolean isLeaf() { return leaf; } } Why is the No Such Element Exception needed?
The Employee Class - 1 public class Employee extends AbstractEmployee { public Employee(String _name, long _salary) { name = _name; salary = _salary; leaf = true; } //-------------------------------------- public Employee(Employee _parent, String _name, long _salary) { name = _name; salary = _salary; parent = _parent; leaf = true; } //-------------------------------------- public long getSalary() { return salary; } //-------------------------------------- public String getName() { return name; }
The Employee Class - 2 public boolean add(Employee e) throws NoSuchElementException { throw new NoSuchElementException("No subordinates"); } //-------------------------------------- public void remove(Employee e) throws NoSuchElementException { throw new NoSuchElementException("No subordinates"); } //-------------------------------------- public Enumeration subordinates () { Vector v = new Vector(); return v.elements (); } //-------------------------------------- public Employee getChild(String s) throws NoSuchElementException { throw new NoSuchElementException("No children"); } //-------------------------------------- public long getSalaries() { return salary; } //-------------------------------------- public Employee getParent() { return parent; } }
The Boss Class - 1 public class Boss extends Employee { Vector employees; public Boss(String _name, long _salary) { super(_name, _salary); leaf = false; employees = new Vector(); } //-------------------------------------- public Boss(Employee _parent, String _name, long _salary) { super(_parent, _name, _salary); leaf = false; employees = new Vector(); } //-------------------------------------- public Boss(Employee emp) { //promotes an employee position to a Boss //and thus allows it to have employees super(emp.getName (), emp.getSalary()); employees = new Vector(); leaf = false; }
The Boss Class - 2 public boolean add(Employee e) throws NoSuchElementException { employees.add(e); return true; } //-------------------------------------- public void remove(Employee e) throws NoSuchElementException { employees.removeElement(e); } //-------------------------------------- public Enumeration subordinates () { return employees.elements (); } //-------------------------------------- public long getSalaries() { long sum = salary; for (int i = 0; i < employees.size(); i++) { sum += ((Employee)employees.elementAt(i)).getSalaries(); } return sum; }
The Boss Class - 3 public Employee getChild(String s) throws NoSuchElementException { Employee newEmp = null; if (getName().equals(s)) return this; else { boolean found = false; Enumeration e = subordinates(); while (e.hasMoreElements() && (! found)) { newEmp = (Employee)e.nextElement(); found = newEmp.getName().equals(s); if (! found) { if (! newEmp.isLeaf ()) { newEmp = newEmp.getChild(s); } else newEmp = null; found =(newEmp != null); } } if (found) return newEmp; else return null; } } }
The Relationships between Classes • What is the component? What is the composite? • Which items are leaves?
Building the Employee Tree • We test our composite design pattern by building and displaying an employee tree • We use a sophisticated GUI tool, called Jtree, to display the employee tree • We cover JTree in chapter 3 of the Deitel book • When an item is clicked, the total of salaries for the person and subordinates appear at the bottom of the applet See that tree !
EmployeeTree - 1 import java.awt.*; import java.awt.event.*; import java.util.*; //swing classes import javax.swing.text.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.border.*; import javax.swing.tree.*; public class empTree extends JxFrame implements TreeSelectionListener { Employee prez, marketVP, prodVP; Employee salesMgr, advMgr; Employee prodMgr, shipMgr; JScrollPane sp; JPanel treePanel; JTree tree; DefaultMutableTreeNode troot; JLabel cost; public empTree() { super("Employee tree"); makeEmployees(); setGUI(); }
EmployeeTree - 2 private void setGUI() { treePanel = new JPanel(); getContentPane().add(treePanel); treePanel.setLayout(new BorderLayout()); sp = new JScrollPane(); treePanel.add("Center", sp); treePanel.add("South", cost = new JLabel(" ")); treePanel.setBorder(new BevelBorder(BevelBorder.RAISED)); troot = new DefaultMutableTreeNode(prez.getName()); tree= new JTree(troot); tree.setBackground(Color.lightGray); loadTree(prez); sp.getViewport().add(tree); setSize(new Dimension(200, 300)); setVisible(true); } public void loadTree(Employee topDog) { DefaultMutableTreeNode troot; troot = new DefaultMutableTreeNode(topDog.getName()); treePanel.remove(tree); tree= new JTree(troot); tree.addTreeSelectionListener(this); sp.getViewport().add(tree); addNodes(troot, topDog); tree.expandRow(0); repaint(); }
EmployeeTree - 3 private void addNodes(DefaultMutableTreeNode pnode, Employee emp) { DefaultMutableTreeNode node; Enumeration e = emp.subordinates(); if (e != null) { while (e.hasMoreElements()) { Employee newEmp = (Employee)e.nextElement(); node = new DefaultMutableTreeNode(newEmp.getName()); pnode.add(node); addNodes(node, newEmp); } } } private void makeEmployees() { prez = new Boss("CEO", 200000); prez.add(marketVP=new Boss("Marketing VP", 100000)); prez.add(prodVP=new Boss("Production VP", 100000)); marketVP.add(salesMgr=new Boss("Sales Mgr", 50000)); marketVP.add(advMgr=new Boss("Advt Mgr", 50000)); //add salesmen reporting to sales manager for (int i=0; i<5; i++) salesMgr .add(new Employee("Sales "+ i, rand_sal(30000))); advMgr.add(new Employee("Secy", 20000)); prodVP.add(prodMgr = new Boss("Prod Mgr", 40000)); prodVP.add(shipMgr = new Boss("Ship Mgr", 35000));
EmployeeTree - 4 //add manufacturing staff for (int i = 0; i < 4; i++) prodMgr.add( new Employee("Manuf "+i, rand_sal(25000))); //add shipping clerks for (int i = 0; i < 3; i++) shipMgr.add( new Employee("ShipClrk "+i, rand_sal(20000))); } private long rand_sal(long salary) { return salary(long)(Math.random()-0.5)*salary/5; } public void valueChanged(TreeSelectionEvent evt) { TreePath path = evt.getPath(); String selectedTerm = path.getLastPathComponent().toString(); Employee emp = prez.getChild(selectedTerm); if (emp != null) cost.setText(new Float(emp.getSalaries()).toString()); } static public void main(String argv[]) { new empTree(); } }